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 "audio/miles.h"
24
25 #include "common/file.h"
26 #include "common/system.h"
27 #include "common/textconsole.h"
28 #include "common/util.h"
29
30 #include "audio/fmopl.h"
31 #include "audio/adlib_ms.h"
32
33 namespace Audio {
34
35 // Miles Audio AdLib/OPL3 driver
36 //
37 // TODO: currently missing: OPL3 4-op voices
38 //
39 // Special cases (great for testing):
40 // - sustain feature is used by Return To Zork (demo) right at the start
41 // - sherlock holmes 2 does lots of priority sorts right at the start of the intro
42
43 #define MILES_ADLIB_VIRTUAL_FMVOICES_COUNT_MAX 20
44 #define MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX 18
45
46 #define MILES_ADLIB_PERCUSSION_BANK 127
47
48 #define MILES_ADLIB_STEREO_PANNING_THRESHOLD_LEFT 27
49 #define MILES_ADLIB_STEREO_PANNING_THRESHOLD_RIGHT 100
50
51 enum kMilesAdLibUpdateFlags {
52 kMilesAdLibUpdateFlags_None = 0,
53 kMilesAdLibUpdateFlags_Reg_20 = 1 << 0,
54 kMilesAdLibUpdateFlags_Reg_40 = 1 << 1,
55 kMilesAdLibUpdateFlags_Reg_60 = 1 << 2, // register 0x6x + 0x8x
56 kMilesAdLibUpdateFlags_Reg_C0 = 1 << 3,
57 kMilesAdLibUpdateFlags_Reg_E0 = 1 << 4,
58 kMilesAdLibUpdateFlags_Reg_A0 = 1 << 5, // register 0xAx + 0xBx
59 kMilesAdLibUpdateFlags_Reg_All = 0x3F
60 };
61
62 uint16 milesAdLibOperator1Register[MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX] = {
63 0x0000, 0x0001, 0x0002, 0x0008, 0x0009, 0x000A, 0x0010, 0x0011, 0x0012,
64 0x0100, 0x0101, 0x0102, 0x0108, 0x0109, 0x010A, 0x0110, 0x0111, 0x0112
65 };
66
67 uint16 milesAdLibOperator2Register[MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX] = {
68 0x0003, 0x0004, 0x0005, 0x000B, 0x000C, 0x000D, 0x0013, 0x0014, 0x0015,
69 0x0103, 0x0104, 0x0105, 0x010B, 0x010C, 0x010D, 0x0113, 0x0114, 0x0115
70 };
71
72 uint16 milesAdLibChannelRegister[MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX] = {
73 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
74 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108
75 };
76
77 struct InstrumentEntry {
78 byte bankId;
79 byte patchId;
80 int16 transposition;
81 byte reg20op1;
82 byte reg40op1;
83 byte reg60op1;
84 byte reg80op1;
85 byte regE0op1;
86 byte reg20op2;
87 byte reg40op2;
88 byte reg60op2;
89 byte reg80op2;
90 byte regE0op2;
91 byte regC0;
92 };
93
94 // hardcoded, dumped from ADLIB.MDI
95 uint16 milesAdLibFrequencyLookUpTable[] = {
96 0x02B2, 0x02B4, 0x02B7, 0x02B9, 0x02BC, 0x02BE, 0x02C1, 0x02C3, 0x02C6, 0x02C9, 0x02CB, 0x02CE,
97 0x02D0, 0x02D3, 0x02D6, 0x02D8, 0x02DB, 0x02DD, 0x02E0, 0x02E3, 0x02E5, 0x02E8, 0x02EB, 0x02ED,
98 0x02F0, 0x02F3, 0x02F6, 0x02F8, 0x02FB, 0x02FE, 0x0301, 0x0303, 0x0306, 0x0309, 0x030C, 0x030F,
99 0x0311, 0x0314, 0x0317, 0x031A, 0x031D, 0x0320, 0x0323, 0x0326, 0x0329, 0x032B, 0x032E, 0x0331,
100 0x0334, 0x0337, 0x033A, 0x033D, 0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0x034F, 0x0352, 0x0356,
101 0x0359, 0x035C, 0x035F, 0x0362, 0x0365, 0x0368, 0x036B, 0x036F, 0x0372, 0x0375, 0x0378, 0x037B,
102 0x037F, 0x0382, 0x0385, 0x0388, 0x038C, 0x038F, 0x0392, 0x0395, 0x0399, 0x039C, 0x039F, 0x03A3,
103 0x03A6, 0x03A9, 0x03AD, 0x03B0, 0x03B4, 0x03B7, 0x03BB, 0x03BE, 0x03C1, 0x03C5, 0x03C8, 0x03CC,
104 0x03CF, 0x03D3, 0x03D7, 0x03DA, 0x03DE, 0x03E1, 0x03E5, 0x03E8, 0x03EC, 0x03F0, 0x03F3, 0x03F7,
105 0x03FB, 0x03FE, 0xFE01, 0xFE03, 0xFE05, 0xFE07, 0xFE08, 0xFE0A, 0xFE0C, 0xFE0E, 0xFE10, 0xFE12,
106 0xFE14, 0xFE16, 0xFE18, 0xFE1A, 0xFE1C, 0xFE1E, 0xFE20, 0xFE21, 0xFE23, 0xFE25, 0xFE27, 0xFE29,
107 0xFE2B, 0xFE2D, 0xFE2F, 0xFE31, 0xFE34, 0xFE36, 0xFE38, 0xFE3A, 0xFE3C, 0xFE3E, 0xFE40, 0xFE42,
108 0xFE44, 0xFE46, 0xFE48, 0xFE4A, 0xFE4C, 0xFE4F, 0xFE51, 0xFE53, 0xFE55, 0xFE57, 0xFE59, 0xFE5C,
109 0xFE5E, 0xFE60, 0xFE62, 0xFE64, 0xFE67, 0xFE69, 0xFE6B, 0xFE6D, 0xFE6F, 0xFE72, 0xFE74, 0xFE76,
110 0xFE79, 0xFE7B, 0xFE7D, 0xFE7F, 0xFE82, 0xFE84, 0xFE86, 0xFE89, 0xFE8B, 0xFE8D, 0xFE90, 0xFE92,
111 0xFE95, 0xFE97, 0xFE99, 0xFE9C, 0xFE9E, 0xFEA1, 0xFEA3, 0xFEA5, 0xFEA8, 0xFEAA, 0xFEAD, 0xFEAF
112 };
113
114 // hardcoded, dumped from ADLIB.MDI
115 uint16 milesAdLibVolumeSensitivityTable[] = {
116 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127
117 };
118
119 // MIDI panning to register volume table for dual OPL2
120 // hardcoded, dumped from ADLIB.MDI
121 uint8 milesAdLibPanningVolumeLookUpTable[] = {
122 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
123 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
124 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94,
125 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 127,
126 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
128 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
129 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127
130 };
131
132 class MidiDriver_Miles_AdLib : public MidiDriver_Multisource {
133 public:
134 MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount);
135 virtual ~MidiDriver_Miles_AdLib();
136
137 // MidiDriver
138 int open() override;
139 void close() override;
140 void send(uint32 b) override;
141 void send(int8 source, uint32 b) override;
142 void metaEvent(int8 source, byte type, byte *data, uint16 length) override;
allocateChannel()143 MidiChannel *allocateChannel() override { return NULL; }
getPercussionChannel()144 MidiChannel *getPercussionChannel() override { return NULL; }
145
isOpen() const146 bool isOpen() const override { return _isOpen; }
getBaseTempo()147 uint32 getBaseTempo() override { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
148
149 void stopAllNotes(uint8 source, uint8 channel) override;
150 void applySourceVolume(uint8 source) override;
151 void deinitSource(uint8 source) override;
152
153 uint32 property(int prop, uint32 param) override;
154
155 void setVolume(byte volume);
156
157 private:
158 OPL::Config::OplType _oplType;
159 byte _modePhysicalFmVoicesCount;
160 byte _modeVirtualFmVoicesCount;
161 bool _modeStereo;
162
163 // the version of Miles AIL/MSS to emulate
164 MilesVersion _milesVersion;
165
166 // Structure to hold information about current status of MIDI Channels
167 struct MidiChannelEntry {
168 byte currentPatchBank;
169 const InstrumentEntry *currentInstrumentPtr;
170 uint16 currentPitchBender;
171 byte currentPitchRange;
172 byte currentVoiceProtection;
173
174 byte currentVolume;
175 byte currentVolumeExpression;
176
177 byte currentPanning;
178
179 byte currentModulation;
180 byte currentSustain;
181
182 byte currentActiveVoicesCount;
183
MidiChannelEntryAudio::MidiDriver_Miles_AdLib::MidiChannelEntry184 MidiChannelEntry() : currentPatchBank(0),
185 currentInstrumentPtr(NULL),
186 currentPitchBender(MIDI_PITCH_BEND_DEFAULT),
187 currentPitchRange(0),
188 currentVoiceProtection(0),
189 currentVolume(0), currentVolumeExpression(0),
190 currentPanning(0),
191 currentModulation(0),
192 currentSustain(0),
193 currentActiveVoicesCount(0) { }
194 };
195
196 // Structure to hold information about current status of virtual FM Voices
197 struct VirtualFmVoiceEntry {
198 bool inUse;
199 byte actualMidiChannel;
200
201 const InstrumentEntry *currentInstrumentPtr;
202
203 bool isPhysical;
204 byte physicalFmVoice;
205
206 uint16 currentPriority;
207
208 byte currentOriginalMidiNote;
209 byte currentNote;
210 int16 currentTransposition;
211 byte currentVelocity;
212
213 bool sustained;
214
VirtualFmVoiceEntryAudio::MidiDriver_Miles_AdLib::VirtualFmVoiceEntry215 VirtualFmVoiceEntry(): inUse(false),
216 actualMidiChannel(0),
217 currentInstrumentPtr(NULL),
218 isPhysical(false), physicalFmVoice(0),
219 currentPriority(0),
220 currentOriginalMidiNote(0),
221 currentNote(0),
222 currentTransposition(0),
223 currentVelocity(0),
224 sustained(false) { }
225 };
226
227 // Structure to hold information about current status of physical FM Voices
228 struct PhysicalFmVoiceEntry {
229 bool inUse;
230 byte virtualFmVoice;
231
232 byte currentB0hReg;
233
PhysicalFmVoiceEntryAudio::MidiDriver_Miles_AdLib::PhysicalFmVoiceEntry234 PhysicalFmVoiceEntry(): inUse(false),
235 virtualFmVoice(0),
236 currentB0hReg(0) { }
237 };
238
239 OPL::OPL *_opl;
240 int _masterVolume;
241
242 bool _isOpen;
243
244 // stores information about all MIDI channels (not the actual OPL FM voice channels!)
245 MidiChannelEntry _midiChannels[MIDI_CHANNEL_COUNT];
246
247 // stores information about all virtual OPL FM voices
248 VirtualFmVoiceEntry _virtualFmVoices[MILES_ADLIB_VIRTUAL_FMVOICES_COUNT_MAX];
249
250 // stores information about all physical OPL FM voices
251 PhysicalFmVoiceEntry _physicalFmVoices[MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX];
252
253 // holds all instruments
254 InstrumentEntry *_instrumentTablePtr;
255 uint16 _instrumentTableCount;
256
257 bool circularPhysicalAssignment;
258 byte circularPhysicalAssignmentFmVoice;
259
260 void resetData();
261 void resetAdLib();
262 void resetAdLibOperatorRegisters(byte baseRegister, byte value);
263 void resetAdLibFMVoiceChannelRegisters(byte baseRegister, byte value);
264
265 void setRegister(int reg, int value);
266 void setRegisterStereo(uint8 reg, uint8 valueLeft, uint8 valueRight);
267
268 int16 searchFreeVirtualFmVoiceChannel();
269 int16 searchFreePhysicalFmVoiceChannel();
270
271 void noteOn(byte midiChannel, byte note, byte velocity);
272 void noteOff(byte midiChannel, byte note);
273
274 void prioritySort();
275
276 void releaseFmVoice(byte virtualFmVoice);
277
278 void releaseSustain(byte midiChannel);
279
280 void updatePhysicalFmVoice(byte virtualFmVoice, bool keyOn, uint16 registerUpdateFlags);
281
282 void controlChange(byte midiChannel, byte controllerNumber, byte controllerValue);
283 void programChange(byte midiChannel, byte patchId);
284
285 const InstrumentEntry *searchInstrument(byte bankId, byte patchId);
286
287 void pitchBendChange(byte MIDIchannel, byte parameter1, byte parameter2);
288 };
289
MidiDriver_Miles_AdLib(InstrumentEntry * instrumentTablePtr,uint16 instrumentTableCount)290 MidiDriver_Miles_AdLib::MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount)
291 : _masterVolume(15), _opl(0), _isOpen(false) {
292
293 _instrumentTablePtr = instrumentTablePtr;
294 _instrumentTableCount = instrumentTableCount;
295
296 // Set up for OPL3, we will downgrade in case we can't create OPL3 emulator
297 // regular AdLib (OPL2) card
298 _oplType = OPL::Config::kOpl3;
299 _modeVirtualFmVoicesCount = 20;
300 _modePhysicalFmVoicesCount = 18;
301 _modeStereo = true;
302
303 // Default to Miles v2
304 _milesVersion = MILES_VERSION_2;
305
306 // Older Miles Audio drivers did not do a circular assign for physical FM-voices
307 // Sherlock Holmes 2 used the circular assign
308 circularPhysicalAssignment = true;
309 // this way the first circular physical FM-voice search will start at FM-voice 0
310 circularPhysicalAssignmentFmVoice = MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX;
311 }
312
~MidiDriver_Miles_AdLib()313 MidiDriver_Miles_AdLib::~MidiDriver_Miles_AdLib() {
314 delete[] _instrumentTablePtr; // is created in factory MidiDriver_Miles_AdLib_create()
315 }
316
open()317 int MidiDriver_Miles_AdLib::open() {
318 if (_oplType == OPL::Config::kOpl3) {
319 // Try to create OPL3 first
320 _opl = OPL::Config::create(OPL::Config::kOpl3);
321 }
322 if (!_opl) {
323 // not created yet, downgrade to dual OPL2
324 _oplType = OPL::Config::kDualOpl2;
325 _opl = OPL::Config::create(OPL::Config::kDualOpl2);
326 }
327 if (!_opl) {
328 // not created yet, downgrade to OPL2
329 _oplType = OPL::Config::kOpl2;
330 _opl = OPL::Config::create(OPL::Config::kOpl2);
331 }
332
333 if (!_opl) {
334 // We still got nothing -> can't do anything anymore
335 return -1;
336 }
337
338 if (_oplType != OPL::Config::kOpl3) {
339 _modeVirtualFmVoicesCount = 16;
340 _modePhysicalFmVoicesCount = 9;
341 _modeStereo = false;
342 }
343
344 _opl->init();
345
346 _isOpen = true;
347
348 resetData();
349
350 _timerRate = getBaseTempo();
351 _opl->start(new Common::Functor0Mem<void, MidiDriver_Miles_AdLib>(this, &MidiDriver_Miles_AdLib::onTimer));
352
353 resetAdLib();
354
355 return 0;
356 }
357
close()358 void MidiDriver_Miles_AdLib::close() {
359 delete _opl;
360 _isOpen = false;
361 }
362
setVolume(byte volume)363 void MidiDriver_Miles_AdLib::setVolume(byte volume) {
364 _masterVolume = volume;
365 //renewNotes(-1, true);
366 }
367
resetData()368 void MidiDriver_Miles_AdLib::resetData() {
369 ARRAYCLEAR(_midiChannels);
370 ARRAYCLEAR(_virtualFmVoices);
371 ARRAYCLEAR(_physicalFmVoices);
372
373 for (byte midiChannel = 0; midiChannel < MIDI_CHANNEL_COUNT; midiChannel++) {
374 // defaults, were sent to driver during driver initialization
375 _midiChannels[midiChannel].currentVolume = 0x7F;
376 _midiChannels[midiChannel].currentPanning = 0x40; // center
377 _midiChannels[midiChannel].currentVolumeExpression = 127;
378
379 // Miles Audio 2: hardcoded pitch range as a global (not channel specific), set to 12
380 // Miles Audio 3: pitch range per MIDI channel; default 2 semitones
381 _midiChannels[midiChannel].currentPitchBender = MIDI_PITCH_BEND_DEFAULT;
382 _midiChannels[midiChannel].currentPitchRange = _milesVersion == MILES_VERSION_3 ? 2 : 12;
383 }
384
385 }
386
resetAdLib()387 void MidiDriver_Miles_AdLib::resetAdLib() {
388 if (_oplType == OPL::Config::kOpl3) {
389 setRegister(0x105, 1); // enable OPL3
390 setRegister(0x104, 0); // activate 18 2-operator FM-voices
391 }
392
393 // enable waveform control on both operators
394 setRegister(0x01, _oplType == OPL::Config::kOpl3 ? 0 : 0x20);
395 if (_oplType == OPL::Config::kOpl3)
396 setRegister(0x101, 0);
397 // Timer control
398 setRegister(0x02, 0);
399 setRegister(0x03, 0);
400 setRegister(0x04, 0x60);
401 setRegister(0x04, 0x80);
402
403 // Set note select and disable CSM mode
404 setRegister(0x08, 0);
405 // disable Rhythm; set vibrato and modulation depth to 1
406 setRegister(0xBD, 0xC0);
407
408 // reset FM voice instrument data
409 resetAdLibOperatorRegisters(0x20, 1);
410 resetAdLibOperatorRegisters(0x40, 0x3F);
411 resetAdLibOperatorRegisters(0x60, 0xFF);
412 resetAdLibOperatorRegisters(0x80, 0x0F);
413 resetAdLibFMVoiceChannelRegisters(0xA0, 0);
414 resetAdLibFMVoiceChannelRegisters(0xB0, 0);
415 resetAdLibFMVoiceChannelRegisters(0xC0, 0);
416 resetAdLibOperatorRegisters(0xE0, 0);
417 }
418
resetAdLibOperatorRegisters(byte baseRegister,byte value)419 void MidiDriver_Miles_AdLib::resetAdLibOperatorRegisters(byte baseRegister, byte value) {
420 byte physicalFmVoice = 0;
421
422 for (physicalFmVoice = 0; physicalFmVoice < _modePhysicalFmVoicesCount; physicalFmVoice++) {
423 setRegister(baseRegister + milesAdLibOperator1Register[physicalFmVoice], value);
424 setRegister(baseRegister + milesAdLibOperator2Register[physicalFmVoice], value);
425 }
426 }
427
resetAdLibFMVoiceChannelRegisters(byte baseRegister,byte value)428 void MidiDriver_Miles_AdLib::resetAdLibFMVoiceChannelRegisters(byte baseRegister, byte value) {
429 byte physicalFmVoice = 0;
430
431 for (physicalFmVoice = 0; physicalFmVoice < _modePhysicalFmVoicesCount; physicalFmVoice++) {
432 setRegister(baseRegister + milesAdLibChannelRegister[physicalFmVoice], value);
433 }
434 }
435
436 // MIDI messages can be found at http://www.midi.org/techspecs/midimessages.php
send(uint32 b)437 void MidiDriver_Miles_AdLib::send(uint32 b) {
438 byte command = b & 0xf0;
439 byte channel = b & 0xf;
440 byte op1 = (b >> 8) & 0xff;
441 byte op2 = (b >> 16) & 0xff;
442
443 switch (command) {
444 case 0x80:
445 noteOff(channel, op1);
446 break;
447 case 0x90:
448 noteOn(channel, op1, op2);
449 break;
450 case 0xb0: // Control change
451 controlChange(channel, op1, op2);
452 break;
453 case 0xc0: // Program Change
454 programChange(channel, op1);
455 break;
456 case 0xa0: // Polyphonic key pressure (aftertouch)
457 case 0xd0: // Channel pressure (aftertouch)
458 // Aftertouch doesn't seem to be implemented in the Miles Audio AdLib driver
459 break;
460 case 0xe0:
461 pitchBendChange(channel, op1, op2);
462 break;
463 case 0xf0: // SysEx
464 warning("MILES-ADLIB: SysEx: %x", b);
465 break;
466 default:
467 warning("MILES-ADLIB: Unknown event %02x", command);
468 }
469 }
470
send(int8 source,uint32 b)471 void MidiDriver_Miles_AdLib::send(int8 source, uint32 b) {
472 // TODO Implement proper multisource support.
473 if (source == -1 || source == 0)
474 send(b);
475 }
476
stopAllNotes(uint8 source,uint8 channel)477 void MidiDriver_Miles_AdLib::stopAllNotes(uint8 source, uint8 channel) {
478 if (!(source == 0 || source == 0xFF))
479 return;
480
481 for (int i = 0; i < _modeVirtualFmVoicesCount; i++) {
482 if (_virtualFmVoices[i].inUse && (channel == 0xFF || _virtualFmVoices[i].actualMidiChannel == channel)) {
483 releaseFmVoice(i);
484 }
485 }
486 }
487
property(int prop,uint32 param)488 uint32 MidiDriver_Miles_AdLib::property(int prop, uint32 param) {
489 switch (prop) {
490 case PROP_MILES_VERSION:
491 if (param == 0xFFFF)
492 return _milesVersion;
493
494 switch (param) {
495 case MILES_VERSION_3:
496 _milesVersion = MILES_VERSION_3;
497 break;
498 case MILES_VERSION_2:
499 default:
500 _milesVersion = MILES_VERSION_2;
501 }
502
503 break;
504 default:
505 return MidiDriver_Multisource::property(prop, param);
506 }
507 return 0;
508 }
509
applySourceVolume(uint8 source)510 void MidiDriver_Miles_AdLib::applySourceVolume(uint8 source) {
511 if (!(source == 0 || source == 0xFF))
512 return;
513
514 for (int i = 0; i < _modeVirtualFmVoicesCount; i++) {
515 if (_virtualFmVoices[i].inUse) {
516 updatePhysicalFmVoice(i, true, kMilesAdLibUpdateFlags_Reg_40);
517 }
518 }
519 }
520
searchFreeVirtualFmVoiceChannel()521 int16 MidiDriver_Miles_AdLib::searchFreeVirtualFmVoiceChannel() {
522 for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
523 if (!_virtualFmVoices[virtualFmVoice].inUse)
524 return virtualFmVoice;
525 }
526 return -1;
527 }
528
searchFreePhysicalFmVoiceChannel()529 int16 MidiDriver_Miles_AdLib::searchFreePhysicalFmVoiceChannel() {
530 if (!circularPhysicalAssignment) {
531 // Older assign logic
532 for (byte physicalFmVoice = 0; physicalFmVoice < _modePhysicalFmVoicesCount; physicalFmVoice++) {
533 if (!_physicalFmVoices[physicalFmVoice].inUse)
534 return physicalFmVoice;
535 }
536 } else {
537 // Newer one
538 // Remembers last physical FM-voice and searches from that spot
539 byte physicalFmVoice = circularPhysicalAssignmentFmVoice;
540 for (byte physicalFmVoiceCount = 0; physicalFmVoiceCount < _modePhysicalFmVoicesCount; physicalFmVoiceCount++) {
541 physicalFmVoice++;
542 if (physicalFmVoice >= _modePhysicalFmVoicesCount)
543 physicalFmVoice = 0;
544 if (!_physicalFmVoices[physicalFmVoice].inUse) {
545 circularPhysicalAssignmentFmVoice = physicalFmVoice;
546 return physicalFmVoice;
547 }
548 }
549 }
550 return -1;
551 }
552
noteOn(byte midiChannel,byte note,byte velocity)553 void MidiDriver_Miles_AdLib::noteOn(byte midiChannel, byte note, byte velocity) {
554 const InstrumentEntry *instrumentPtr = NULL;
555
556 if (velocity == 0) {
557 noteOff(midiChannel, note);
558 return;
559 }
560
561 if (midiChannel == 9) {
562 // percussion channel
563 // search for instrument according to given note
564 instrumentPtr = searchInstrument(MILES_ADLIB_PERCUSSION_BANK, note);
565 } else {
566 // directly get instrument of channel
567 instrumentPtr = _midiChannels[midiChannel].currentInstrumentPtr;
568 }
569 if (!instrumentPtr) {
570 warning("MILES-ADLIB: noteOn: invalid instrument");
571 return;
572 }
573
574 //warning("Note On: channel %d, note %d, velocity %d, instrument %d/%d", midiChannel, note, velocity, instrumentPtr->bankId, instrumentPtr->patchId);
575
576 // look for free virtual FM voice
577 int16 virtualFmVoice = searchFreeVirtualFmVoiceChannel();
578
579 if (virtualFmVoice == -1) {
580 // Out of virtual voices, can't do anything about it
581 return;
582 }
583
584 // Scale back velocity
585 velocity = (velocity & 0x7F) >> 3;
586 velocity = milesAdLibVolumeSensitivityTable[velocity];
587
588 if (midiChannel != 9) {
589 _virtualFmVoices[virtualFmVoice].currentNote = note;
590 _virtualFmVoices[virtualFmVoice].currentTransposition = instrumentPtr->transposition;
591 } else {
592 // Percussion channel
593 _virtualFmVoices[virtualFmVoice].currentNote = instrumentPtr->transposition;
594 _virtualFmVoices[virtualFmVoice].currentTransposition = 0;
595 }
596
597 _virtualFmVoices[virtualFmVoice].inUse = true;
598 _virtualFmVoices[virtualFmVoice].actualMidiChannel = midiChannel;
599 _virtualFmVoices[virtualFmVoice].currentOriginalMidiNote = note;
600 _virtualFmVoices[virtualFmVoice].currentInstrumentPtr = instrumentPtr;
601 _virtualFmVoices[virtualFmVoice].currentVelocity = velocity;
602 _virtualFmVoices[virtualFmVoice].isPhysical = false;
603 _virtualFmVoices[virtualFmVoice].sustained = false;
604 _virtualFmVoices[virtualFmVoice].currentPriority = 32767;
605
606 int16 physicalFmVoice = searchFreePhysicalFmVoiceChannel();
607 if (physicalFmVoice == -1) {
608 // None found
609 // go through priorities and reshuffle voices
610 prioritySort();
611 return;
612 }
613
614 // Another voice active on this MIDI channel
615 _midiChannels[midiChannel].currentActiveVoicesCount++;
616
617 // Mark virtual FM-Voice as being connected to physical FM-Voice
618 _virtualFmVoices[virtualFmVoice].isPhysical = true;
619 _virtualFmVoices[virtualFmVoice].physicalFmVoice = physicalFmVoice;
620
621 // Mark physical FM-Voice as being connected to virtual FM-Voice
622 _physicalFmVoices[physicalFmVoice].inUse = true;
623 _physicalFmVoices[physicalFmVoice].virtualFmVoice = virtualFmVoice;
624
625 // Update the physical FM-Voice
626 updatePhysicalFmVoice(virtualFmVoice, true, kMilesAdLibUpdateFlags_Reg_All);
627 }
628
noteOff(byte midiChannel,byte note)629 void MidiDriver_Miles_AdLib::noteOff(byte midiChannel, byte note) {
630 //warning("Note Off: channel %d, note %d", midiChannel, note);
631
632 // Search through all virtual FM-Voices for current midiChannel + note
633 for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
634 if (_virtualFmVoices[virtualFmVoice].inUse) {
635 if ((_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) && (_virtualFmVoices[virtualFmVoice].currentOriginalMidiNote == note)) {
636 // found one
637 if (_midiChannels[midiChannel].currentSustain >= 64) {
638 _virtualFmVoices[virtualFmVoice].sustained = true;
639 continue;
640 }
641 //
642 releaseFmVoice(virtualFmVoice);
643 }
644 }
645 }
646 }
647
prioritySort()648 void MidiDriver_Miles_AdLib::prioritySort() {
649 byte virtualFmVoice = 0;
650 uint16 virtualPriority = 0;
651 uint16 virtualPriorities[MILES_ADLIB_VIRTUAL_FMVOICES_COUNT_MAX];
652 uint16 virtualFmVoicesCount = 0;
653 byte midiChannel = 0;
654
655 ARRAYCLEAR(virtualPriorities);
656
657 //warning("prioritysort");
658
659 // First calculate priorities for all virtual FM voices, that are in use
660 for (virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
661 if (_virtualFmVoices[virtualFmVoice].inUse) {
662 virtualFmVoicesCount++;
663
664 midiChannel = _virtualFmVoices[virtualFmVoice].actualMidiChannel;
665 if (_midiChannels[midiChannel].currentVoiceProtection >= 64) {
666 // Voice protection enabled
667 virtualPriority = 0xFFFF;
668 } else {
669 virtualPriority = _virtualFmVoices[virtualFmVoice].currentPriority;
670 }
671 byte currentActiveVoicesCount = _midiChannels[midiChannel].currentActiveVoicesCount;
672 if (virtualPriority >= currentActiveVoicesCount) {
673 virtualPriority -= _midiChannels[midiChannel].currentActiveVoicesCount;
674 } else {
675 virtualPriority = 0; // overflow, should never happen
676 }
677 virtualPriorities[virtualFmVoice] = virtualPriority;
678 }
679 }
680
681 //
682 while (virtualFmVoicesCount) {
683 uint16 unvoicedHighestPriority = 0;
684 byte unvoicedHighestFmVoice = 0;
685 uint16 voicedLowestPriority = 65535;
686 byte voicedLowestFmVoice = 0;
687
688 for (virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
689 if (_virtualFmVoices[virtualFmVoice].inUse) {
690 virtualPriority = virtualPriorities[virtualFmVoice];
691 if (!_virtualFmVoices[virtualFmVoice].isPhysical) {
692 // currently not physical, so unvoiced
693 if (virtualPriority >= unvoicedHighestPriority) {
694 unvoicedHighestPriority = virtualPriority;
695 unvoicedHighestFmVoice = virtualFmVoice;
696 }
697 } else {
698 // currently physical, so voiced
699 if (virtualPriority <= voicedLowestPriority) {
700 voicedLowestPriority = virtualPriority;
701 voicedLowestFmVoice = virtualFmVoice;
702 }
703 }
704 }
705 }
706
707 if (unvoicedHighestPriority < voicedLowestPriority)
708 break; // We are done
709
710 if (unvoicedHighestPriority == 0)
711 break;
712
713 // Safety checks
714 assert(_virtualFmVoices[voicedLowestFmVoice].isPhysical);
715 assert(!_virtualFmVoices[unvoicedHighestFmVoice].isPhysical);
716
717 // Steal this physical voice
718 byte physicalFmVoice = _virtualFmVoices[voicedLowestFmVoice].physicalFmVoice;
719
720 //warning("MILES-ADLIB: stealing physical FM-Voice %d from virtual FM-Voice %d for virtual FM-Voice %d", physicalFmVoice, voicedLowestFmVoice, unvoicedHighestFmVoice);
721 //warning("priority old %d, priority new %d", unvoicedHighestPriority, voicedLowestPriority);
722
723 releaseFmVoice(voicedLowestFmVoice);
724
725 // Get some data of the unvoiced highest priority virtual FM Voice
726 midiChannel = _virtualFmVoices[unvoicedHighestFmVoice].actualMidiChannel;
727
728 // Another voice active on this MIDI channel
729 _midiChannels[midiChannel].currentActiveVoicesCount++;
730
731 // Mark virtual FM-Voice as being connected to physical FM-Voice
732 _virtualFmVoices[unvoicedHighestFmVoice].isPhysical = true;
733 _virtualFmVoices[unvoicedHighestFmVoice].physicalFmVoice = physicalFmVoice;
734
735 // Mark physical FM-Voice as being connected to virtual FM-Voice
736 _physicalFmVoices[physicalFmVoice].inUse = true;
737 _physicalFmVoices[physicalFmVoice].virtualFmVoice = unvoicedHighestFmVoice;
738
739 // Update the physical FM-Voice
740 updatePhysicalFmVoice(unvoicedHighestFmVoice, true, kMilesAdLibUpdateFlags_Reg_All);
741
742 virtualFmVoicesCount--;
743 }
744 }
745
releaseFmVoice(byte virtualFmVoice)746 void MidiDriver_Miles_AdLib::releaseFmVoice(byte virtualFmVoice) {
747 // virtual Voice not actually played? -> exit
748 if (!_virtualFmVoices[virtualFmVoice].isPhysical) {
749 _virtualFmVoices[virtualFmVoice].inUse = false;
750 return;
751 }
752
753 byte midiChannel = _virtualFmVoices[virtualFmVoice].actualMidiChannel;
754 byte physicalFmVoice = _virtualFmVoices[virtualFmVoice].physicalFmVoice;
755
756 // stop note from playing
757 updatePhysicalFmVoice(virtualFmVoice, false, kMilesAdLibUpdateFlags_Reg_A0);
758
759 // this virtual FM voice isn't physical anymore
760 _virtualFmVoices[virtualFmVoice].isPhysical = false;
761 _virtualFmVoices[virtualFmVoice].inUse = false;
762
763 // Remove physical FM-Voice from being active
764 _physicalFmVoices[physicalFmVoice].inUse = false;
765
766 // One less voice active on this MIDI channel
767 assert(_midiChannels[midiChannel].currentActiveVoicesCount);
768 _midiChannels[midiChannel].currentActiveVoicesCount--;
769 }
770
releaseSustain(byte midiChannel)771 void MidiDriver_Miles_AdLib::releaseSustain(byte midiChannel) {
772 // Search through all virtual FM-Voices for currently sustained notes and call noteOff on them
773 for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
774 if (_virtualFmVoices[virtualFmVoice].inUse) {
775 if ((_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) && (_virtualFmVoices[virtualFmVoice].sustained)) {
776 // is currently sustained
777 // so do a noteOff (which will check current sustain controller)
778 noteOff(midiChannel, _virtualFmVoices[virtualFmVoice].currentOriginalMidiNote);
779 }
780 }
781 }
782 }
783
updatePhysicalFmVoice(byte virtualFmVoice,bool keyOn,uint16 registerUpdateFlags)784 void MidiDriver_Miles_AdLib::updatePhysicalFmVoice(byte virtualFmVoice, bool keyOn, uint16 registerUpdateFlags) {
785 byte midiChannel = _virtualFmVoices[virtualFmVoice].actualMidiChannel;
786
787 if (!_virtualFmVoices[virtualFmVoice].isPhysical) {
788 // virtual FM-Voice has no physical FM-Voice assigned? -> ignore
789 return;
790 }
791
792 byte physicalFmVoice = _virtualFmVoices[virtualFmVoice].physicalFmVoice;
793 const InstrumentEntry *instrumentPtr = _virtualFmVoices[virtualFmVoice].currentInstrumentPtr;
794
795 uint16 op1Reg = milesAdLibOperator1Register[physicalFmVoice];
796 uint16 op2Reg = milesAdLibOperator2Register[physicalFmVoice];
797 uint16 channelReg = milesAdLibChannelRegister[physicalFmVoice];
798
799 uint16 compositeVolume = 0;
800 uint8 leftVolume = 0;
801 uint8 rightVolume = 0;
802
803 if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_40) {
804 // Calculate new volume
805 byte midiVolume = _midiChannels[midiChannel].currentVolume;
806 byte midiVolumeExpression = _midiChannels[midiChannel].currentVolumeExpression;
807 compositeVolume = midiVolume * midiVolumeExpression * 2;
808
809 compositeVolume = compositeVolume >> 8; // get upmost 8 bits
810 if (compositeVolume)
811 compositeVolume++; // round up in case result wasn't 0
812
813 compositeVolume = compositeVolume * _virtualFmVoices[virtualFmVoice].currentVelocity * 2;
814 compositeVolume = compositeVolume >> 8; // get upmost 8 bits
815 if (compositeVolume)
816 compositeVolume++; // round up in case result wasn't 0
817
818 // Scale by source volume.
819 compositeVolume = compositeVolume * _sources[0].volume / _sources[0].neutralVolume;
820 if (_userVolumeScaling) {
821 if (_userMute) {
822 compositeVolume = 0;
823 } else {
824 // Scale by user volume.
825 uint16 userVolume = (_sources[0].type == SOURCE_TYPE_SFX ? _userSfxVolume : _userMusicVolume); // Treat SOURCE_TYPE_UNDEFINED as music
826 compositeVolume = (compositeVolume * userVolume) >> 8;
827 }
828 }
829 // Source volume scaling might clip volume, so reduce to maximum.
830 compositeVolume = MIN(compositeVolume, (uint16)0x7F);
831
832 if (_oplType == OPL::Config::kDualOpl2) {
833 // For dual OPL2, Miles pans the notes by playing the same note on
834 // the left and right OPL2 chips at different volume levels.
835 // Calculate the volume for each chip based on the panning value.
836 leftVolume = (milesAdLibPanningVolumeLookUpTable[_midiChannels[midiChannel].currentPanning] * compositeVolume) >> 7;
837 if (leftVolume)
838 leftVolume++; // round up in case result wasn't 0
839 uint8 invertedPanning = 0 - (_midiChannels[midiChannel].currentPanning - 127);
840 rightVolume = (milesAdLibPanningVolumeLookUpTable[invertedPanning] * compositeVolume) >> 7;
841 if (rightVolume)
842 rightVolume++; // round up in case result wasn't 0
843 }
844 }
845
846 if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_20) {
847 // Amplitude Modulation / Vibrato / Envelope Generator Type / Keyboard Scaling Rate / Modulator Frequency Multiple
848 byte reg20op1 = instrumentPtr->reg20op1;
849 byte reg20op2 = instrumentPtr->reg20op2;
850
851 if (_midiChannels[midiChannel].currentModulation >= 64) {
852 // set bit 6 (Vibrato)
853 reg20op1 |= 0x40;
854 reg20op2 |= 0x40;
855 }
856 setRegister(0x20 + op1Reg, reg20op1);
857 setRegister(0x20 + op2Reg, reg20op2);
858 }
859
860 if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_40) {
861 // Volume (Level Key Scaling / Total Level)
862 byte reg40op1 = instrumentPtr->reg40op1;
863 byte reg40op2 = instrumentPtr->reg40op2;
864
865 uint16 volumeOp1 = (~reg40op1) & 0x3F;
866 uint16 volumeOp2 = (~reg40op2) & 0x3F;
867
868 if (_oplType != OPL::Config::kDualOpl2) {
869 if (instrumentPtr->regC0 & 1) {
870 // operator 2 enabled
871 // scale volume factor
872 volumeOp1 = (volumeOp1 * compositeVolume) / 127;
873 // 2nd operator always scaled
874 }
875
876 volumeOp2 = (volumeOp2 * compositeVolume) / 127;
877
878 volumeOp1 = (~volumeOp1) & 0x3F; // negate it, so we get the proper value for the register
879 volumeOp2 = (~volumeOp2) & 0x3F; // ditto
880 reg40op1 = (reg40op1 & 0xC0) | volumeOp1; // keep "scaling level" and merge in our volume
881 reg40op2 = (reg40op2 & 0xC0) | volumeOp2;
882
883 setRegister(0x40 + op1Reg, reg40op1);
884 setRegister(0x40 + op2Reg, reg40op2);
885 } else {
886 // For dual OPL2, separate register values are calculated for the
887 // left and right OPL2 chip.
888 uint8 volumeLeftOp1 = volumeOp1;
889 uint8 volumeRightOp1 = volumeOp1;
890
891 if (instrumentPtr->regC0 & 1) {
892 // operator 2 enabled
893 // scale volume factor
894 volumeLeftOp1 = (volumeLeftOp1 * leftVolume) / 127;
895 volumeRightOp1 = (volumeRightOp1 * rightVolume) / 127;
896 // 2nd operator always scaled
897 }
898
899 uint8 volumeLeftOp2 = (volumeOp2 * leftVolume) / 127;
900 uint8 volumeRightOp2 = (volumeOp2 * rightVolume) / 127;
901
902 volumeLeftOp1 = (~volumeLeftOp1) & 0x3F; // negate it, so we get the proper value for the register
903 volumeRightOp1 = (~volumeRightOp1) & 0x3F;
904 volumeLeftOp2 = (~volumeLeftOp2) & 0x3F; // ditto
905 volumeRightOp2 = (~volumeRightOp2) & 0x3F;
906 uint8 reg40op1left = (reg40op1 & 0xC0) | volumeLeftOp1; // keep "scaling level" and merge in our volume
907 uint8 reg40op1right = (reg40op1 & 0xC0) | volumeRightOp1;
908 uint8 reg40op2left = (reg40op2 & 0xC0) | volumeLeftOp2;
909 uint8 reg40op2right = (reg40op2 & 0xC0) | volumeRightOp2;
910
911 setRegisterStereo(0x40 + op1Reg, reg40op1left, reg40op1right);
912 setRegisterStereo(0x40 + op2Reg, reg40op2left, reg40op2right);
913 }
914 }
915
916 if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_60) {
917 // Attack Rate / Decay Rate
918 // Sustain Level / Release Rate
919 byte reg60op1 = instrumentPtr->reg60op1;
920 byte reg60op2 = instrumentPtr->reg60op2;
921 byte reg80op1 = instrumentPtr->reg80op1;
922 byte reg80op2 = instrumentPtr->reg80op2;
923
924 setRegister(0x60 + op1Reg, reg60op1);
925 setRegister(0x60 + op2Reg, reg60op2);
926 setRegister(0x80 + op1Reg, reg80op1);
927 setRegister(0x80 + op2Reg, reg80op2);
928 }
929
930 if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_E0) {
931 // Waveform Select
932 byte regE0op1 = instrumentPtr->regE0op1;
933 byte regE0op2 = instrumentPtr->regE0op2;
934
935 setRegister(0xE0 + op1Reg, regE0op1);
936 setRegister(0xE0 + op2Reg, regE0op2);
937 }
938
939 if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_C0) {
940 // Feedback / Algorithm
941 byte regC0 = instrumentPtr->regC0;
942
943 if (_oplType == OPL::Config::kOpl3) {
944 // Panning for OPL3
945 byte panning = _midiChannels[midiChannel].currentPanning;
946
947 if (panning <= MILES_ADLIB_STEREO_PANNING_THRESHOLD_LEFT) {
948 regC0 |= 0x20; // left speaker only
949 } else if (panning >= MILES_ADLIB_STEREO_PANNING_THRESHOLD_RIGHT) {
950 regC0 |= 0x10; // right speaker only
951 } else {
952 regC0 |= 0x30; // center
953 }
954 }
955
956 setRegister(0xC0 + channelReg, regC0);
957 }
958
959 if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_A0) {
960 // Frequency / Key-On
961 // Octave / F-Number / Key-On
962 if (!keyOn) {
963 // turn off note
964 byte regB0 = _physicalFmVoices[physicalFmVoice].currentB0hReg & 0x1F; // remove bit 5 "key on"
965 setRegister(0xB0 + channelReg, regB0);
966
967 } else {
968 // turn on note, calculate frequency, octave...
969 int16 pitchBender = _midiChannels[midiChannel].currentPitchBender;
970 byte pitchRange = _midiChannels[midiChannel].currentPitchRange;
971 int16 currentNote = _virtualFmVoices[virtualFmVoice].currentNote;
972 int16 physicalNote = 0;
973 int16 halfTone = 0;
974 uint16 frequency = 0;
975 uint16 frequencyIdx = 0;
976 byte octave = 0;
977
978 pitchBender -= 0x2000;
979 pitchBender = pitchBender >> 5; // divide by 32
980 pitchBender = pitchBender * pitchRange; // pitchrange 12: now +0x0C00 to -0xC00
981 // difference between Miles Audio 2 + 3
982 // Miles Audio 2 used a pitch range of 12, which was basically hardcoded
983 // Miles Audio 3 used an array, which got set by control change events
984
985 currentNote += _virtualFmVoices->currentTransposition;
986
987 // Normalize note
988 currentNote -= 24;
989 do {
990 currentNote += 12;
991 } while (currentNote < 0);
992 currentNote += 12;
993
994 do {
995 currentNote -= 12;
996 } while (currentNote > 95);
997
998 // combine note + pitchbender, also adjust by 8 for rounding
999 currentNote = (currentNote << 8) + pitchBender + 8;
1000
1001 currentNote = currentNote >> 4; // get actual note
1002
1003 // Normalize
1004 currentNote -= (12 * 16);
1005 do {
1006 currentNote += (12 * 16);
1007 } while (currentNote < 0);
1008
1009 currentNote += (12 * 16);
1010 do {
1011 currentNote -= (12 * 16);
1012 } while (currentNote > ((96 * 16) - 1));
1013
1014 physicalNote = currentNote >> 4;
1015
1016 halfTone = physicalNote % 12; // remainder of physicalNote / 12
1017
1018 frequencyIdx = (halfTone << 4) + (currentNote & 0x0F);
1019 assert(frequencyIdx < sizeof(milesAdLibFrequencyLookUpTable));
1020 frequency = milesAdLibFrequencyLookUpTable[frequencyIdx];
1021
1022 octave = (physicalNote / 12) - 1;
1023
1024 if (frequency & 0x8000)
1025 octave++;
1026
1027 if (octave & 0x80) {
1028 octave++;
1029 frequency = frequency >> 1;
1030 }
1031
1032 byte regA0 = frequency & 0xFF;
1033 byte regB0 = ((frequency >> 8) & 0x03) | (octave << 2) | 0x20;
1034
1035 setRegister(0xA0 + channelReg, regA0);
1036 setRegister(0xB0 + channelReg, regB0);
1037
1038 _physicalFmVoices[physicalFmVoice].currentB0hReg = regB0;
1039 }
1040 }
1041
1042 //warning("end of update voice");
1043 }
1044
controlChange(byte midiChannel,byte controllerNumber,byte controllerValue)1045 void MidiDriver_Miles_AdLib::controlChange(byte midiChannel, byte controllerNumber, byte controllerValue) {
1046 uint16 registerUpdateFlags = kMilesAdLibUpdateFlags_None;
1047
1048 switch (controllerNumber) {
1049 case MILES_CONTROLLER_SELECT_PATCH_BANK:
1050 //warning("patch bank channel %d, bank %x", midiChannel, controllerValue);
1051 _midiChannels[midiChannel].currentPatchBank = controllerValue;
1052 break;
1053
1054 case MILES_CONTROLLER_PROTECT_VOICE:
1055 _midiChannels[midiChannel].currentVoiceProtection = controllerValue;
1056 break;
1057
1058 case MILES_CONTROLLER_PROTECT_TIMBRE:
1059 // It seems that this can get ignored, because we don't cache timbres at all
1060 break;
1061
1062 case MIDI_CONTROLLER_MODULATION:
1063 _midiChannels[midiChannel].currentModulation = controllerValue;
1064 registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_20;
1065 break;
1066
1067 case MIDI_CONTROLLER_VOLUME:
1068 _midiChannels[midiChannel].currentVolume = controllerValue;
1069 registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_40;
1070 break;
1071
1072 case MIDI_CONTROLLER_EXPRESSION:
1073 _midiChannels[midiChannel].currentVolumeExpression = controllerValue;
1074 registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_40;
1075 break;
1076
1077 case MIDI_CONTROLLER_PANNING:
1078 _midiChannels[midiChannel].currentPanning = controllerValue;
1079 if (_modeStereo) {
1080 // Update register only in case we are in stereo mode
1081 registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_C0;
1082 }
1083 break;
1084
1085 case MIDI_CONTROLLER_SUSTAIN:
1086 _midiChannels[midiChannel].currentSustain = controllerValue;
1087 if (controllerValue < 64) {
1088 releaseSustain(midiChannel);
1089 }
1090 break;
1091
1092 case MILES_CONTROLLER_PITCH_RANGE:
1093 // Note that this is in fact the MIDI data entry MSB controller. To use
1094 // this to set pitch bend range, the pitch bend range RPN should first
1095 // be selected using the RPN MSB and LSB controllers.
1096 // MSS does not support the RPN controllers and assumes that any use of
1097 // the data entry MSB controller is to set the pitch bend range.
1098
1099 // Miles Audio 3 feature
1100 if (_milesVersion == MILES_VERSION_3)
1101 _midiChannels[midiChannel].currentPitchRange = controllerValue;
1102 break;
1103
1104 case MIDI_CONTROLLER_RESET_ALL_CONTROLLERS:
1105 _midiChannels[midiChannel].currentSustain = 0;
1106 releaseSustain(midiChannel);
1107 _midiChannels[midiChannel].currentModulation = 0;
1108 _midiChannels[midiChannel].currentVolumeExpression = 127;
1109 _midiChannels[midiChannel].currentPitchBender = MIDI_PITCH_BEND_DEFAULT;
1110 registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_20 | kMilesAdLibUpdateFlags_Reg_40 | kMilesAdLibUpdateFlags_Reg_A0;
1111 break;
1112
1113 case MIDI_CONTROLLER_ALL_NOTES_OFF:
1114 for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
1115 if (_virtualFmVoices[virtualFmVoice].inUse) {
1116 // used
1117 if (_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) {
1118 // by our current MIDI channel -> noteOff
1119 noteOff(midiChannel, _virtualFmVoices[virtualFmVoice].currentNote);
1120 }
1121 }
1122 }
1123 break;
1124
1125 default:
1126 //warning("MILES-ADLIB: Unsupported control change %d", controllerNumber);
1127 break;
1128 }
1129
1130 if (registerUpdateFlags) {
1131 for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
1132 if (_virtualFmVoices[virtualFmVoice].inUse) {
1133 // used
1134 if (_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) {
1135 // by our current MIDI channel -> update
1136 updatePhysicalFmVoice(virtualFmVoice, true, registerUpdateFlags);
1137 }
1138 }
1139 }
1140 }
1141 }
1142
programChange(byte midiChannel,byte patchId)1143 void MidiDriver_Miles_AdLib::programChange(byte midiChannel, byte patchId) {
1144 const InstrumentEntry *instrumentPtr = NULL;
1145 byte patchBank = _midiChannels[midiChannel].currentPatchBank;
1146
1147 //warning("patch channel %d, patch %x, bank %x", midiChannel, patchId, patchBank);
1148
1149 // we check, if we actually have data for the requested instrument...
1150 instrumentPtr = searchInstrument(patchBank, patchId);
1151 if (!instrumentPtr) {
1152 warning("MILES-ADLIB: unknown instrument requested (%d, %d)", patchBank, patchId);
1153 return;
1154 }
1155
1156 // and remember it in that case for the current MIDI-channel
1157 _midiChannels[midiChannel].currentInstrumentPtr = instrumentPtr;
1158 }
1159
searchInstrument(byte bankId,byte patchId)1160 const InstrumentEntry *MidiDriver_Miles_AdLib::searchInstrument(byte bankId, byte patchId) {
1161 const InstrumentEntry *instrumentPtr = _instrumentTablePtr;
1162
1163 for (uint16 instrumentNr = 0; instrumentNr < _instrumentTableCount; instrumentNr++) {
1164 if ((instrumentPtr->bankId == bankId) && (instrumentPtr->patchId == patchId)) {
1165 return instrumentPtr;
1166 }
1167 instrumentPtr++;
1168 }
1169
1170 return NULL;
1171 }
1172
pitchBendChange(byte midiChannel,byte parameter1,byte parameter2)1173 void MidiDriver_Miles_AdLib::pitchBendChange(byte midiChannel, byte parameter1, byte parameter2) {
1174 // Miles Audio actually didn't shift parameter 2 1 down in here
1175 // which means in memory it used a 15-bit pitch bender, which also means the default was 0x4000
1176 if ((parameter1 & 0x80) || (parameter2 & 0x80)) {
1177 warning("MILES-ADLIB: invalid pitch bend change");
1178 return;
1179 }
1180 _midiChannels[midiChannel].currentPitchBender = parameter1 | (parameter2 << 7);
1181 for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
1182 if (_virtualFmVoices[virtualFmVoice].inUse) {
1183 // used
1184 if (_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) {
1185 // by our current MIDI channel -> update
1186 updatePhysicalFmVoice(virtualFmVoice, true, kMilesAdLibUpdateFlags_Reg_A0);
1187 }
1188 }
1189 }
1190 }
1191
metaEvent(int8 source,byte type,byte * data,uint16 length)1192 void MidiDriver_Miles_AdLib::metaEvent(int8 source, byte type, byte *data, uint16 length) {
1193 if (type == MIDI_META_END_OF_TRACK && source >= 0)
1194 // Stop hanging notes and release resources used by this source.
1195 deinitSource(source);
1196 }
1197
deinitSource(uint8 source)1198 void MidiDriver_Miles_AdLib::deinitSource(uint8 source) {
1199 if (!(source == 0 || source == 0xFF))
1200 return;
1201
1202 // Turn off sustained notes.
1203 for (int i = 0; i < MIDI_CHANNEL_COUNT; i++) {
1204 controlChange(i, MIDI_CONTROLLER_SUSTAIN, 0);
1205 }
1206
1207 // Stop fades and turn off non-sustained notes.
1208 MidiDriver_Multisource::deinitSource(source);
1209 }
1210
setRegister(int reg,int value)1211 void MidiDriver_Miles_AdLib::setRegister(int reg, int value) {
1212 if (!(reg & 0x100) || _oplType == OPL::Config::kDualOpl2) {
1213 _opl->write(0x220, reg);
1214 _opl->write(0x221, value);
1215 //warning("OPL write %x %x (%d)", reg, value, value);
1216 }
1217 if ((reg & 0x100) || _oplType == OPL::Config::kDualOpl2) {
1218 _opl->write(0x222, reg & 0xFF);
1219 _opl->write(0x223, value);
1220 //warning("OPL3 write %x %x (%d)", reg & 0xFF, value, value);
1221 }
1222 }
1223
setRegisterStereo(uint8 reg,uint8 valueLeft,uint8 valueRight)1224 void MidiDriver_Miles_AdLib::setRegisterStereo(uint8 reg, uint8 valueLeft, uint8 valueRight) {
1225 _opl->write(0x220, reg);
1226 _opl->write(0x221, valueLeft);
1227 _opl->write(0x222, reg);
1228 _opl->write(0x223, valueRight);
1229 }
1230
MidiDriver_Miles_AdLib_create(const Common::String & filenameAdLib,const Common::String & filenameOPL3,Common::SeekableReadStream * streamAdLib,Common::SeekableReadStream * streamOPL3)1231 MidiDriver_Multisource *MidiDriver_Miles_AdLib_create(const Common::String &filenameAdLib, const Common::String &filenameOPL3, Common::SeekableReadStream *streamAdLib, Common::SeekableReadStream *streamOPL3) {
1232 // Load adlib instrument data from file SAMPLE.AD (OPL3: SAMPLE.OPL)
1233 Common::String timbreFilename;
1234 Common::SeekableReadStream *timbreStream = nullptr;
1235
1236 bool preferOPL3 = false;
1237
1238 Common::File *fileStream = new Common::File();
1239 uint32 fileSize = 0;
1240 uint32 fileDataOffset = 0;
1241 uint32 fileDataLeft = 0;
1242
1243
1244 uint32 streamSize = 0;
1245 byte *streamDataPtr = nullptr;
1246
1247 byte curBankId = 0;
1248 byte curPatchId = 0;
1249
1250 InstrumentEntry *instrumentTablePtr = nullptr;
1251 uint16 instrumentTableCount = 0;
1252 InstrumentEntry *instrumentPtr = nullptr;
1253 uint32 instrumentOffset = 0;
1254 uint16 instrumentDataSize = 0;
1255
1256 // Logic:
1257 // We prefer OPL3 timbre data in case OPL3 is available in ScummVM
1258 // If it's not or OPL3 timbre data is not available, we go for AdLib timbre data
1259 // And if OPL3 is not available in ScummVM and also AdLib timbre data is not available,
1260 // we then still go for OPL3 timbre data.
1261 //
1262 // Note: for most games OPL3 timbre data + AdLib timbre data is the same.
1263 // And at least in theory we should still be able to use OPL3 timbre data even for AdLib.
1264 // However there is a special OPL3-specific timbre format, which is currently not supported.
1265 // In this case the error message "unsupported instrument size" should appear. I haven't found
1266 // a game that uses it, which is why I haven't implemented it yet.
1267
1268 if (OPL::Config::detect(OPL::Config::kOpl3) >= 0) {
1269 // OPL3 available, prefer OPL3 timbre data because of this
1270 preferOPL3 = true;
1271 }
1272
1273 // Check if streams were passed to us and select one of them
1274 if ((streamAdLib) || (streamOPL3)) {
1275 // At least one stream was passed by caller
1276 if (preferOPL3) {
1277 // Prefer OPL3 timbre stream in case OPL3 is available
1278 timbreStream = streamOPL3;
1279 }
1280 if (!timbreStream) {
1281 // Otherwise prefer AdLib timbre stream first
1282 if (streamAdLib) {
1283 timbreStream = streamAdLib;
1284 } else {
1285 // If not available, use OPL3 timbre stream
1286 if (streamOPL3) {
1287 timbreStream = streamOPL3;
1288 }
1289 }
1290 }
1291 }
1292
1293 // Now check if any filename was passed to us
1294 if ((!filenameAdLib.empty()) || (!filenameOPL3.empty())) {
1295 // If that's the case, check if one of those exists
1296 if (preferOPL3) {
1297 // OPL3 available
1298 if (!filenameOPL3.empty()) {
1299 if (fileStream->exists(filenameOPL3)) {
1300 // If OPL3 available, prefer OPL3 timbre file in case file exists
1301 timbreFilename = filenameOPL3;
1302 }
1303 }
1304 if (timbreFilename.empty()) {
1305 if (!filenameAdLib.empty()) {
1306 if (fileStream->exists(filenameAdLib)) {
1307 // otherwise use AdLib timbre file, if it exists
1308 timbreFilename = filenameAdLib;
1309 }
1310 }
1311 }
1312 } else {
1313 // OPL3 not available
1314 // Prefer the AdLib one for now
1315 if (!filenameAdLib.empty()) {
1316 if (fileStream->exists(filenameAdLib)) {
1317 // if AdLib file exists, use it
1318 timbreFilename = filenameAdLib;
1319 }
1320 }
1321 if (timbreFilename.empty()) {
1322 if (!filenameOPL3.empty()) {
1323 if (fileStream->exists(filenameOPL3)) {
1324 // if OPL3 file exists, use it
1325 timbreFilename = filenameOPL3;
1326 }
1327 }
1328 }
1329 }
1330 if (timbreFilename.empty() && (!timbreStream)) {
1331 // If none of them exists and also no stream was passed, we can't do anything about it
1332 if (!filenameAdLib.empty()) {
1333 if (!filenameOPL3.empty()) {
1334 error("MILES-ADLIB: could not open timbre file (%s or %s)", filenameAdLib.c_str(), filenameOPL3.c_str());
1335 } else {
1336 error("MILES-ADLIB: could not open timbre file (%s)", filenameAdLib.c_str());
1337 }
1338 } else {
1339 error("MILES-ADLIB: could not open timbre file (%s)", filenameOPL3.c_str());
1340 }
1341 }
1342 }
1343
1344 if (!timbreFilename.empty()) {
1345 // Filename was passed to us and file exists (this is the common case for most games)
1346 // We prefer this situation
1347
1348 if (!fileStream->open(timbreFilename))
1349 error("MILES-ADLIB: could not open timbre file (%s)", timbreFilename.c_str());
1350
1351 streamSize = fileStream->size();
1352
1353 streamDataPtr = new byte[streamSize];
1354
1355 if (fileStream->read(streamDataPtr, streamSize) != streamSize)
1356 error("MILES-ADLIB: error while reading timbre file (%s)", timbreFilename.c_str());
1357 fileStream->close();
1358
1359 } else if (timbreStream) {
1360 // Timbre data was passed directly (possibly read from resource file by caller)
1361 // Currently used by "Amazon Guardians of Eden", "Simon 2" and "Return To Zork"
1362 streamSize = timbreStream->size();
1363
1364 streamDataPtr = new byte[streamSize];
1365
1366 if (timbreStream->read(streamDataPtr, streamSize) != streamSize)
1367 error("MILES-ADLIB: error while reading timbre stream");
1368
1369 } else {
1370 error("MILES-ADLIB: timbre filenames nor timbre stream were passed");
1371 }
1372
1373 delete fileStream;
1374
1375 // File is like this:
1376 // [patch:BYTE] [bank:BYTE] [patchoffset:UINT32]
1377 // ...
1378 // until patch + bank are both 0xFF, which signals end of header
1379
1380 // First we check how many entries there are
1381 fileDataOffset = 0;
1382 fileDataLeft = streamSize;
1383 while (1) {
1384 if (fileDataLeft < 6)
1385 error("MILES-ADLIB: unexpected EOF in instrument file");
1386
1387 curPatchId = streamDataPtr[fileDataOffset++];
1388 curBankId = streamDataPtr[fileDataOffset++];
1389
1390 if ((curBankId == 0xFF) && (curPatchId == 0xFF))
1391 break;
1392
1393 fileDataOffset += 4; // skip over offset
1394 instrumentTableCount++;
1395 }
1396
1397 if (instrumentTableCount == 0)
1398 error("MILES-ADLIB: no instruments in instrument file");
1399
1400 // Allocate space for instruments
1401 instrumentTablePtr = new InstrumentEntry[instrumentTableCount];
1402
1403 // Now actually read all entries
1404 instrumentPtr = instrumentTablePtr;
1405
1406 fileDataOffset = 0;
1407 fileDataLeft = fileSize;
1408 while (1) {
1409 curPatchId = streamDataPtr[fileDataOffset++];
1410 curBankId = streamDataPtr[fileDataOffset++];
1411
1412 if ((curBankId == 0xFF) && (curPatchId == 0xFF))
1413 break;
1414
1415 instrumentOffset = READ_LE_UINT32(streamDataPtr + fileDataOffset);
1416 fileDataOffset += 4;
1417
1418 instrumentPtr->bankId = curBankId;
1419 instrumentPtr->patchId = curPatchId;
1420
1421 instrumentDataSize = READ_LE_UINT16(streamDataPtr + instrumentOffset);
1422 if (instrumentDataSize != 14)
1423 error("MILES-ADLIB: unsupported instrument size");
1424
1425 instrumentPtr->transposition = (signed char)streamDataPtr[instrumentOffset + 2];
1426 instrumentPtr->reg20op1 = streamDataPtr[instrumentOffset + 3];
1427 instrumentPtr->reg40op1 = streamDataPtr[instrumentOffset + 4];
1428 instrumentPtr->reg60op1 = streamDataPtr[instrumentOffset + 5];
1429 instrumentPtr->reg80op1 = streamDataPtr[instrumentOffset + 6];
1430 instrumentPtr->regE0op1 = streamDataPtr[instrumentOffset + 7];
1431 instrumentPtr->regC0 = streamDataPtr[instrumentOffset + 8];
1432 instrumentPtr->reg20op2 = streamDataPtr[instrumentOffset + 9];
1433 instrumentPtr->reg40op2 = streamDataPtr[instrumentOffset + 10];
1434 instrumentPtr->reg60op2 = streamDataPtr[instrumentOffset + 11];
1435 instrumentPtr->reg80op2 = streamDataPtr[instrumentOffset + 12];
1436 instrumentPtr->regE0op2 = streamDataPtr[instrumentOffset + 13];
1437
1438 // Instrument read, next instrument please
1439 instrumentPtr++;
1440 }
1441
1442 // Free instrument file/stream data
1443 delete[] streamDataPtr;
1444
1445 return new MidiDriver_Miles_AdLib(instrumentTablePtr, instrumentTableCount);
1446 }
1447
1448 } // End of namespace Audio
1449