driver_adlib.cpp
1 /* 2 Copyright (C) 1994-1995 Apogee Software, Ltd. 3 Copyright (C) 2009 Jonathon Fowler <jf@jonof.id.au> 4 Copyright (C) EDuke32 developers and contributors 5 6 This program is free software; you can redistribute it and/or 7 modify it under the terms of the GNU General Public License 8 as published by the Free Software Foundation; either version 2 9 of the License, or (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 15 See the 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 21 */ 22 /********************************************************************** 23 module: AL_MIDI.C 24 25 author: James R. Dose 26 date: April 1, 1994 27 28 Low level routines to support General MIDI music on AdLib compatible 29 cards. 30 31 (c) Copyright 1994 James R. Dose. All Rights Reserved. 32 **********************************************************************/ 33 34 #include "driver_adlib.h" 35 36 #include "_al_midi.h" 37 #include "_multivc.h" 38 #include "compat.h" 39 #include "midi.h" 40 #include "midifuncs.h" 41 #include "opl3.h" 42 #include "opl3_reg.h" 43 44 enum 45 { 46 AdLibErr_Error = -1, 47 AdLibErr_Ok = 0, 48 }; 49 50 static int AL_Volume = MIDI_MaxVolume; 51 static opl3_chip AL_Chip; 52 53 static void AL_Shutdown(void); 54 static int ErrorCode; 55 56 int AdLibDrv_GetError(void) { return ErrorCode; } 57 58 const char *AdLibDrv_ErrorString(int const ErrorNumber) 59 { 60 switch (ErrorNumber) 61 { 62 case AdLibErr_Error: return AdLibDrv_ErrorString(ErrorCode); 63 case AdLibErr_Ok: return "AdLib ok."; 64 default: return "Unknown AdLib error."; 65 } 66 } 67 68 int AdLibDrv_MIDI_Init(midifuncs * const funcs) 69 { 70 AdLibDrv_MIDI_Shutdown(); 71 Bmemset(funcs, 0, sizeof(midifuncs)); 72 73 funcs->NoteOff = AL_NoteOff; 74 funcs->NoteOn = AL_NoteOn; 75 funcs->PolyAftertouch = nullptr; 76 funcs->ControlChange = AL_ControlChange; 77 funcs->ProgramChange = AL_ProgramChange; 78 funcs->ChannelAftertouch = nullptr; 79 funcs->PitchBend = AL_SetPitchBend; 80 funcs->SetVolume = AL_SetVolume; 81 82 AL_Volume = MIDI_MaxVolume; 83 84 return AdLibErr_Ok; 85 } 86 87 void AdLibDrv_MIDI_HaltPlayback(void) { MV_UnhookMusicRoutine(); } 88 89 void AdLibDrv_MIDI_Shutdown(void) 90 { 91 AdLibDrv_MIDI_HaltPlayback(); 92 AL_Shutdown(); 93 } 94 95 int AdLibDrv_MIDI_StartPlayback(void) 96 { 97 AdLibDrv_MIDI_HaltPlayback(); 98 99 AL_Init(); 100 MV_HookMusicRoutine(AdLibDrv_MIDI_Service); 101 102 return MIDI_Ok; 103 } 104 105 void AdLibDrv_MIDI_SetTempo(int const tempo, int const division) 106 { 107 MV_MIDIRenderTempo = tempo * division / 60; 108 MV_MIDIRenderTimer = 0; 109 } 110 111 void AdLibDrv_MIDI_Service(void) 112 { 113 int16_t * buffer16 = (int16_t *)MV_MusicBuffer; 114 115 for (int i = 0; i < MV_MIXBUFFERSIZE; i++) 116 { 117 int16_t buf[2]; 118 while (MV_MIDIRenderTimer >= MV_MixRate) 119 { 120 if (MV_MIDIRenderTempo >= 0) 121 MIDI_ServiceRoutine(); 122 MV_MIDIRenderTimer -= MV_MixRate; 123 } 124 if (MV_MIDIRenderTempo >= 0) MV_MIDIRenderTimer += MV_MIDIRenderTempo; 125 OPL3_GenerateResampled(&AL_Chip, buf); 126 if (MV_Channels == 2) 127 { 128 *buffer16++ = clamp((buf[0] * AL_PostAmp * AL_Volume * (1.f / MIDI_MaxVolume)), INT16_MIN, INT16_MAX); 129 *buffer16++ = clamp((buf[1] * AL_PostAmp * AL_Volume * (1.f / MIDI_MaxVolume)), INT16_MIN, INT16_MAX); 130 } 131 else 132 *buffer16++ = clamp(((buf[0] + buf[1]) * AL_PostAmp * AL_Volume * (.5f / MIDI_MaxVolume)), INT16_MIN, INT16_MAX); 133 } 134 } 135 136 137 /* Definition of octave information to be ORed onto F-Number */ 138 139 static uint32_t constexpr OctavePitch[MAX_OCTAVE+1] = { 140 0x0000, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, 141 }; 142 143 static uint32_t NoteMod12[MAX_NOTE+1]; 144 static uint32_t NoteDiv12[MAX_NOTE+1]; 145 146 // Pitch table 147 148 //static unsigned NotePitch[FINETUNE_MAX+1][12] = 149 // { 150 // { C, C_SHARP, D, D_SHARP, E, F, F_SHARP, G, G_SHARP, A, A_SHARP, B }, 151 // }; 152 153 static uint32_t constexpr NotePitch[FINETUNE_MAX+1][12] = { 154 { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287 }, 155 { 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x242, 0x264, 0x288 }, 156 { 0x158, 0x16c, 0x182, 0x199, 0x1b1, 0x1cb, 0x1e6, 0x203, 0x221, 0x243, 0x265, 0x289 }, 157 { 0x158, 0x16c, 0x183, 0x19a, 0x1b2, 0x1cc, 0x1e7, 0x204, 0x222, 0x244, 0x266, 0x28a }, 158 { 0x159, 0x16d, 0x183, 0x19a, 0x1b3, 0x1cd, 0x1e8, 0x205, 0x223, 0x245, 0x267, 0x28b }, 159 { 0x15a, 0x16e, 0x184, 0x19b, 0x1b3, 0x1ce, 0x1e9, 0x206, 0x224, 0x246, 0x268, 0x28c }, 160 { 0x15a, 0x16e, 0x185, 0x19c, 0x1b4, 0x1ce, 0x1ea, 0x207, 0x225, 0x247, 0x269, 0x28e }, 161 { 0x15b, 0x16f, 0x185, 0x19d, 0x1b5, 0x1cf, 0x1eb, 0x208, 0x226, 0x248, 0x26a, 0x28f }, 162 { 0x15b, 0x170, 0x186, 0x19d, 0x1b6, 0x1d0, 0x1ec, 0x209, 0x227, 0x249, 0x26b, 0x290 }, 163 { 0x15c, 0x170, 0x187, 0x19e, 0x1b7, 0x1d1, 0x1ec, 0x20a, 0x228, 0x24a, 0x26d, 0x291 }, 164 { 0x15d, 0x171, 0x188, 0x19f, 0x1b7, 0x1d2, 0x1ed, 0x20b, 0x229, 0x24b, 0x26e, 0x292 }, 165 { 0x15d, 0x172, 0x188, 0x1a0, 0x1b8, 0x1d3, 0x1ee, 0x20c, 0x22a, 0x24c, 0x26f, 0x293 }, 166 { 0x15e, 0x172, 0x189, 0x1a0, 0x1b9, 0x1d4, 0x1ef, 0x20d, 0x22b, 0x24d, 0x270, 0x295 }, 167 { 0x15f, 0x173, 0x18a, 0x1a1, 0x1ba, 0x1d4, 0x1f0, 0x20e, 0x22c, 0x24e, 0x271, 0x296 }, 168 { 0x15f, 0x174, 0x18a, 0x1a2, 0x1bb, 0x1d5, 0x1f1, 0x20f, 0x22d, 0x24f, 0x272, 0x297 }, 169 { 0x160, 0x174, 0x18b, 0x1a3, 0x1bb, 0x1d6, 0x1f2, 0x210, 0x22e, 0x250, 0x273, 0x298 }, 170 { 0x161, 0x175, 0x18c, 0x1a3, 0x1bc, 0x1d7, 0x1f3, 0x211, 0x22f, 0x251, 0x274, 0x299 }, 171 { 0x161, 0x176, 0x18c, 0x1a4, 0x1bd, 0x1d8, 0x1f4, 0x212, 0x230, 0x252, 0x276, 0x29b }, 172 { 0x162, 0x176, 0x18d, 0x1a5, 0x1be, 0x1d9, 0x1f5, 0x212, 0x231, 0x254, 0x277, 0x29c }, 173 { 0x162, 0x177, 0x18e, 0x1a6, 0x1bf, 0x1d9, 0x1f5, 0x213, 0x232, 0x255, 0x278, 0x29d }, 174 { 0x163, 0x178, 0x18f, 0x1a6, 0x1bf, 0x1da, 0x1f6, 0x214, 0x233, 0x256, 0x279, 0x29e }, 175 { 0x164, 0x179, 0x18f, 0x1a7, 0x1c0, 0x1db, 0x1f7, 0x215, 0x235, 0x257, 0x27a, 0x29f }, 176 { 0x164, 0x179, 0x190, 0x1a8, 0x1c1, 0x1dc, 0x1f8, 0x216, 0x236, 0x258, 0x27b, 0x2a1 }, 177 { 0x165, 0x17a, 0x191, 0x1a9, 0x1c2, 0x1dd, 0x1f9, 0x217, 0x237, 0x259, 0x27c, 0x2a2 }, 178 { 0x166, 0x17b, 0x192, 0x1aa, 0x1c3, 0x1de, 0x1fa, 0x218, 0x238, 0x25a, 0x27e, 0x2a3 }, 179 { 0x166, 0x17b, 0x192, 0x1aa, 0x1c3, 0x1df, 0x1fb, 0x219, 0x239, 0x25b, 0x27f, 0x2a4 }, 180 { 0x167, 0x17c, 0x193, 0x1ab, 0x1c4, 0x1e0, 0x1fc, 0x21a, 0x23a, 0x25c, 0x280, 0x2a6 }, 181 { 0x168, 0x17d, 0x194, 0x1ac, 0x1c5, 0x1e0, 0x1fd, 0x21b, 0x23b, 0x25d, 0x281, 0x2a7 }, 182 { 0x168, 0x17d, 0x194, 0x1ad, 0x1c6, 0x1e1, 0x1fe, 0x21c, 0x23c, 0x25e, 0x282, 0x2a8 }, 183 { 0x169, 0x17e, 0x195, 0x1ad, 0x1c7, 0x1e2, 0x1ff, 0x21d, 0x23d, 0x260, 0x283, 0x2a9 }, 184 { 0x16a, 0x17f, 0x196, 0x1ae, 0x1c8, 0x1e3, 0x1ff, 0x21e, 0x23e, 0x261, 0x284, 0x2ab }, 185 { 0x16a, 0x17f, 0x197, 0x1af, 0x1c8, 0x1e4, 0x200, 0x21f, 0x23f, 0x262, 0x286, 0x2ac } 186 }; 187 188 // Slot numbers as a function of the voice and the operator. 189 // ( melodic only) 190 191 static int constexpr slotVoice[NUMADLIBVOICES][2] = { 192 { 0, 3 }, // voice 0 193 { 1, 4 }, // 1 194 { 2, 5 }, // 2 195 { 6, 9 }, // 3 196 { 7, 10 }, // 4 197 { 8, 11 }, // 5 198 { 12, 15 }, // 6 199 { 13, 16 }, // 7 200 { 14, 17 }, // 8 201 }; 202 203 static int VoiceLevel[AL_NumChipSlots][2]; 204 static int VoiceKsl[AL_NumChipSlots][2]; 205 206 // This table gives the offset of each slot within the chip. 207 // offset = fn( slot) 208 209 static int8_t constexpr offsetSlot[AL_NumChipSlots] = { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 }; 210 211 static int VoiceReserved[NUMADLIBVOICES * 2]; 212 213 static AdLibVoice Voice[NUMADLIBVOICES * 2]; 214 static AdLibVoiceList Voice_Pool; 215 216 static AdLibChannel Channel[NUMADLIBCHANNELS]; 217 218 static int constexpr AL_LeftPort = ADLIB_PORT; 219 static int constexpr AL_RightPort = ADLIB_PORT + 2; 220 221 static int constexpr AL_MaxMidiChannel = ARRAY_SIZE(Channel); 222 223 int AL_Stereo = TRUE; 224 int AL_AdditiveMode; 225 226 float AL_PostAmp = 3.f; 227 228 // TODO: clean up this shit... 229 #define OFFSET(structure, offset) (*((char **)&(structure)[offset])) 230 231 #define LL_AddToTail(type, listhead, node) \ 232 LL_AddNode((char *)(node), (char **)&((listhead)->end), (char **)&((listhead)->start), (intptr_t)offsetof(type, prev), \ 233 (intptr_t)offsetof(type, next)) 234 235 #define LL_Remove(type, listhead, node) \ 236 LL_RemoveNode((char *)(node), (char **)&((listhead)->start), (char **)&((listhead)->end), (intptr_t)offsetof(type, next), \ 237 (intptr_t)offsetof(type, prev)) 238 239 static void LL_RemoveNode(char * __restrict item, char ** __restrict head, char ** __restrict tail, intptr_t next, intptr_t prev) 240 { 241 if (OFFSET(item, prev) == nullptr) 242 *head = OFFSET(item, next); 243 else 244 OFFSET(OFFSET(item, prev), next) = OFFSET(item, next); 245 246 if (OFFSET(item, next) == nullptr) 247 *tail = OFFSET(item, prev); 248 else 249 OFFSET(OFFSET(item, next), prev) = OFFSET(item, prev); 250 251 OFFSET(item, next) = nullptr; 252 OFFSET(item, prev) = nullptr; 253 } 254 255 static void LL_AddNode(char * __restrict item, char ** __restrict head, char ** __restrict tail, intptr_t next, intptr_t prev) 256 { 257 OFFSET(item, prev) = nullptr; 258 OFFSET(item, next) = *head; 259 260 if (*head) 261 OFFSET(*head, prev) = item; 262 else 263 *tail = item; 264 265 *head = item; 266 } 267 268 269 static FORCE_INLINE void AL_SendOutputToPort(int const port, int const reg, int const data) 270 { 271 OPL3_WriteRegBuffered(&AL_Chip, (uint16_t)(reg + ((port & 2) << 7)), (uint8_t)data); 272 } 273 274 275 static FORCE_INLINE void AL_SendOutput(int const voice, int const reg, int const data) 276 { 277 AL_SendOutputToPort(voice ? AL_LeftPort : AL_RightPort, reg, data); 278 } 279 280 281 static void AL_SetVoiceTimbre(int const voice) 282 { 283 int const channel = Voice[voice].channel; 284 int const patch = (channel == 9) ? Voice[voice].key + 128 : Channel[channel].Timbre; 285 286 if (Voice[voice].timbre == patch) 287 return; 288 289 Voice[voice].timbre = patch; 290 291 auto const timbre = &ADLIB_TimbreBank[patch]; 292 293 int const port = Voice[voice].port; 294 int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; 295 int slot = slotVoice[voc][0]; 296 int off = offsetSlot[slot]; 297 298 VoiceLevel[slot][port] = OPL3_TOTAL_LEVEL_MASK - (timbre->Level[0] & OPL3_TOTAL_LEVEL_MASK); 299 VoiceKsl[slot][port] = timbre->Level[0] & OPL3_KSL_MASK; 300 301 AL_SendOutput(port, OPL3_FNUM_LOW + voc, 0); 302 AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, 0); 303 304 // Let voice clear the release 305 AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, 0xff); 306 307 AL_SendOutput(port, OPL3_ATTACK_DECAY + off, timbre->Env1[0]); 308 AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, timbre->Env2[0]); 309 AL_SendOutput(port, OPL3_ENABLE_WAVE_SELECT + off, timbre->SAVEK[0]); 310 AL_SendOutput(port, OPL3_WAVE_SELECT + off, timbre->Wave[0]); 311 312 AL_SendOutput(port, OPL3_KSL_LEVEL + off, timbre->Level[0]); 313 slot = slotVoice[voc][1]; 314 315 AL_SendOutput(port, OPL3_FEEDBACK_CONNECTION + voc, 316 (timbre->Feedback & (OPL3_FEEDBACK_MASK | OPL3_CONNECTION_BIT)) | OPL3_STEREO_BITS); 317 318 off = offsetSlot[slot]; 319 320 VoiceLevel[slot][port] = OPL3_TOTAL_LEVEL_MASK - (timbre->Level[1] & OPL3_TOTAL_LEVEL_MASK); 321 VoiceKsl[slot][port] = timbre->Level[1] & OPL3_KSL_MASK; 322 323 AL_SendOutput(port, OPL3_KSL_LEVEL + off, OPL3_TOTAL_LEVEL_MASK); 324 325 // Let voice clear the release 326 AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, 0xff); 327 328 AL_SendOutput(port, OPL3_ATTACK_DECAY + off, timbre->Env1[1]); 329 AL_SendOutput(port, OPL3_SUSTAIN_RELEASE + off, timbre->Env2[1]); 330 AL_SendOutput(port, OPL3_ENABLE_WAVE_SELECT + off, timbre->SAVEK[1]); 331 AL_SendOutput(port, OPL3_WAVE_SELECT + off, timbre->Wave[1]); 332 } 333 334 335 static void AL_SetVoiceVolume(int const voice) 336 { 337 int const channel = Voice[voice].channel; 338 auto const timbre = &ADLIB_TimbreBank[Voice[voice].timbre]; 339 int const velocity = min<int>(Voice[voice].velocity + timbre->Velocity, MAX_VELOCITY); 340 341 int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; 342 int const slot = slotVoice[voc][1]; 343 int const port = Voice[voice].port; 344 345 // amplitude 346 auto t1 = (uint32_t)VoiceLevel[slot][port] * (velocity + 0x80); 347 t1 = (Channel[channel].Volume * t1) >> 15; 348 349 uint32_t volume = t1 ^ OPL3_TOTAL_LEVEL_MASK; 350 volume |= (uint32_t)VoiceKsl[slot][port]; 351 352 AL_SendOutput(port, OPL3_KSL_LEVEL + offsetSlot[slot], volume); 353 354 // Check if this timbre is Additive 355 if (timbre->Feedback & 0x01) 356 { 357 int const slot = slotVoice[voc][0]; 358 uint32_t t2; 359 360 // amplitude 361 if (AL_AdditiveMode) 362 t1 = (uint32_t)VoiceLevel[slot][port] * (velocity + 0x80); 363 364 t2 = (Channel[channel].Volume * t1) >> 15; 365 366 volume = t2 ^ OPL3_TOTAL_LEVEL_MASK; 367 volume |= (uint32_t)VoiceKsl[slot][port]; 368 369 AL_SendOutput(port, OPL3_KSL_LEVEL + offsetSlot[slot], volume); 370 } 371 } 372 373 374 static int AL_AllocVoice(void) 375 { 376 if (!Voice_Pool.start) 377 return AL_VoiceNotFound; 378 379 int const voice = Voice_Pool.start->num; 380 LL_Remove(AdLibVoice, &Voice_Pool, &Voice[voice]); 381 return voice; 382 } 383 384 385 static int AL_GetVoice(int const channel, int const key) 386 { 387 auto const *voice = Channel[channel].Voices.start; 388 389 while (voice != nullptr) 390 { 391 if (voice->key == (uint32_t)key) 392 return voice->num; 393 voice = voice->next; 394 } 395 396 return AL_VoiceNotFound; 397 } 398 399 400 static void AL_SetVoicePitch(int const voice) 401 { 402 int const port = Voice[voice].port; 403 int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; 404 int const channel = Voice[voice].channel; 405 406 int patch, note; 407 408 if (channel == 9) 409 { 410 patch = Voice[voice].key + 128; 411 note = ADLIB_TimbreBank[patch].Transpose; 412 } 413 else 414 { 415 patch = Channel[channel].Timbre; 416 note = Voice[voice].key + ADLIB_TimbreBank[patch].Transpose; 417 } 418 419 note += Channel[channel].KeyOffset - 12; 420 note = clamp(note, 0, MAX_NOTE); 421 422 int detune = Channel[channel].KeyDetune; 423 424 int ScaleNote = NoteMod12[note]; 425 int Octave = NoteDiv12[note]; 426 427 int pitch = OctavePitch[Octave] | NotePitch[detune][ScaleNote]; 428 429 Voice[voice].pitchleft = pitch; 430 431 pitch |= Voice[voice].status; 432 433 AL_SendOutput(port, OPL3_FNUM_LOW + voc, pitch); 434 AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, pitch >> 8); 435 } 436 437 static void AL_SetVoicePan(int const voice) 438 { 439 int const port = Voice[voice].port; 440 int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; 441 int const channel = Voice[voice].channel; 442 443 if (AL_Stereo) 444 AL_SendOutput(port, 0xD0 + voc, Channel[channel].Pan << 1); 445 } 446 447 448 static void AL_SetChannelVolume(int const channel, int const volume) 449 { 450 Channel[channel].Volume = clamp(volume, 0, AL_MaxVolume); 451 452 auto voice = Channel[channel].Voices.start; 453 454 while (voice != nullptr) 455 { 456 AL_SetVoiceVolume(voice->num); 457 voice = voice->next; 458 } 459 } 460 461 462 static void AL_SetChannelPan(int const channel, int const pan) 463 { 464 // Don't pan drum sounds 465 if (channel != 9) 466 Channel[channel].Pan = pan; 467 468 auto voice = Channel[channel].Voices.start; 469 while (voice != nullptr) 470 { 471 AL_SetVoicePan(voice->num); 472 voice = voice->next; 473 } 474 } 475 476 477 static void AL_SetChannelDetune(int const channel, int const detune) { Channel[channel].Detune = detune; } 478 479 480 static void AL_ResetVoices(void) 481 { 482 Voice_Pool.start = nullptr; 483 Voice_Pool.end = nullptr; 484 485 int const numvoices = NUMADLIBVOICES * 2; 486 487 for (int index = 0; index < numvoices; index++) 488 { 489 if (VoiceReserved[index] == FALSE) 490 { 491 Voice[index].num = index; 492 Voice[index].key = 0; 493 Voice[index].velocity = 0; 494 Voice[index].channel = -1; 495 Voice[index].timbre = -1; 496 Voice[index].port = (index < NUMADLIBVOICES) ? 0 : 1; 497 Voice[index].status = NOTE_OFF; 498 LL_AddToTail(AdLibVoice, &Voice_Pool, &Voice[index]); 499 } 500 } 501 502 for (int index = 0; index < NUMADLIBCHANNELS; index++) 503 { 504 Channel[index] = {}; 505 Channel[index].Volume = AL_DefaultChannelVolume; 506 Channel[index].Pan = 64; 507 Channel[index].PitchBendRange = AL_DefaultPitchBendRange; 508 Channel[index].PitchBendSemiTones = AL_DefaultPitchBendRange / 100; 509 Channel[index].PitchBendHundreds = AL_DefaultPitchBendRange % 100; 510 } 511 } 512 513 514 static void AL_CalcPitchInfo(void) 515 { 516 for (int note = 0; note <= MAX_NOTE; note++) 517 { 518 NoteMod12[note] = note % 12; 519 NoteDiv12[note] = note / 12; 520 } 521 522 #if 0 523 for (int finetune = 1; finetune <= FINETUNE_MAX; finetune++) 524 { 525 double detune = pow(2, (double)finetune / (12.0 * FINETUNE_RANGE)); 526 527 for (int note = 0; note < 12; note++) 528 NotePitch[finetune][note] = ((double)NotePitch[0][note] * detune); 529 } 530 #endif 531 } 532 533 534 static void AL_FlushCard(int const port) 535 { 536 for (int i = 0; i < NUMADLIBVOICES; i++) 537 { 538 if (VoiceReserved[i]) 539 continue; 540 541 auto slot1 = offsetSlot[slotVoice[i][0]]; 542 auto slot2 = offsetSlot[slotVoice[i][1]]; 543 544 AL_SendOutputToPort(port, OPL3_FNUM_LOW + i, 0); 545 AL_SendOutputToPort(port, OPL3_KEYON_BLOCK + i, 0); 546 547 AL_SendOutputToPort(port, OPL3_WAVE_SELECT + slot1, 0); 548 AL_SendOutputToPort(port, OPL3_WAVE_SELECT + slot2, 0); 549 550 // Set the envelope to be fast and quiet 551 AL_SendOutputToPort(port, OPL3_ATTACK_DECAY + slot1, 0xff); 552 AL_SendOutputToPort(port, OPL3_ATTACK_DECAY + slot2, 0xff); 553 AL_SendOutputToPort(port, OPL3_SUSTAIN_RELEASE + slot1, 0xff); 554 AL_SendOutputToPort(port, OPL3_SUSTAIN_RELEASE + slot2, 0xff); 555 556 // Maximum attenuation 557 AL_SendOutputToPort(port, OPL3_KSL_LEVEL + slot1, 0xff); 558 AL_SendOutputToPort(port, OPL3_KSL_LEVEL + slot2, 0xff); 559 } 560 } 561 562 563 static void AL_Reset(void) 564 { 565 AL_SendOutputToPort(ADLIB_PORT, 1, OPL3_ENABLE_WAVE_SELECT); 566 AL_SendOutputToPort(ADLIB_PORT, OPL3_KBD_SPLIT_REGISTER, 0); 567 568 // Set the values: AM Depth, VIB depth & Rhythm 569 AL_SendOutputToPort(ADLIB_PORT, OPL3_PERCUSSION_REGISTER, 0); 570 571 AL_SetStereo(AL_Stereo); 572 573 AL_FlushCard(AL_LeftPort); 574 AL_FlushCard(AL_RightPort); 575 } 576 577 578 void AL_SetStereo(int const stereo) { AL_SendOutputToPort(AL_RightPort, OPL3_MODE_REGISTER, (stereo << 1) + 1); } 579 580 581 static void AL_NoteOff(int const channel, int const key, int velocity) 582 { 583 UNREFERENCED_PARAMETER(velocity); 584 585 // We only play channels 1 through 10 586 if (channel >= AL_MaxMidiChannel) 587 return; 588 589 int const voice = AL_GetVoice(channel, key); 590 591 if (voice == AL_VoiceNotFound) 592 return; 593 594 Voice[voice].status = NOTE_OFF; 595 596 int const port = Voice[voice].port; 597 int const voc = (voice >= NUMADLIBVOICES) ? voice - NUMADLIBVOICES : voice; 598 599 AL_SendOutput(port, OPL3_KEYON_BLOCK + voc, hibyte(Voice[voice].pitchleft)); 600 601 LL_Remove(AdLibVoice, &Channel[channel].Voices, &Voice[voice]); 602 LL_AddToTail(AdLibVoice, &Voice_Pool, &Voice[voice]); 603 } 604 605 606 static void AL_NoteOn(int const channel, int const key, int const velocity) 607 { 608 // We only play channels 1 through 10 609 if (channel >= AL_MaxMidiChannel) 610 return; 611 612 if (velocity == 0) 613 { 614 AL_NoteOff(channel, key, velocity); 615 return; 616 } 617 618 int voice = AL_AllocVoice(); 619 620 if (voice == AL_VoiceNotFound) 621 { 622 if (Channel[9].Voices.start) 623 { 624 AL_NoteOff(9, Channel[9].Voices.start->key, 0); 625 voice = AL_AllocVoice(); 626 } 627 628 if (voice == AL_VoiceNotFound) 629 return; 630 } 631 632 Voice[voice].key = key; 633 Voice[voice].channel = channel; 634 Voice[voice].velocity = velocity; 635 Voice[voice].status = NOTE_ON; 636 637 LL_AddToTail(AdLibVoice, &Channel[channel].Voices, &Voice[voice]); 638 639 AL_SetVoiceTimbre(voice); 640 AL_SetVoiceVolume(voice); 641 AL_SetVoicePitch(voice); 642 AL_SetVoicePan(voice); 643 } 644 645 646 static FORCE_INLINE void AL_AllNotesOff(int const channel) 647 { 648 while (Channel[channel].Voices.start != nullptr) 649 AL_NoteOff(channel, Channel[channel].Voices.start->key, 0); 650 } 651 652 653 static void AL_ControlChange(int const channel, int const type, int const data) 654 { 655 // We only play channels 1 through 10 656 if (channel >= AL_MaxMidiChannel) 657 return; 658 659 switch (type) 660 { 661 case MIDI_VOLUME: 662 AL_SetChannelVolume(channel, data); 663 break; 664 665 case MIDI_PAN: 666 AL_SetChannelPan(channel, data); 667 break; 668 669 case MIDI_DETUNE: 670 AL_SetChannelDetune(channel, data); 671 break; 672 673 case MIDI_ALL_NOTES_OFF: 674 AL_AllNotesOff(channel); 675 break; 676 677 case MIDI_RESET_ALL_CONTROLLERS: 678 AL_ResetVoices(); 679 AL_SetChannelVolume(channel, AL_DefaultChannelVolume); 680 AL_SetChannelPan(channel, 64); 681 AL_SetChannelDetune(channel, 0); 682 break; 683 684 case MIDI_RPN_MSB: 685 Channel[channel].RPN &= 0x00FF; 686 Channel[channel].RPN |= (data & 0xFF) << 8; 687 break; 688 689 case MIDI_RPN_LSB: 690 Channel[channel].RPN &= 0xFF00; 691 Channel[channel].RPN |= data & 0xFF; 692 break; 693 694 case MIDI_DATAENTRY_MSB: 695 if (Channel[channel].RPN == MIDI_PITCHBEND_MSB) 696 { 697 Channel[channel].PitchBendSemiTones = data; 698 Channel[channel].PitchBendRange = Channel[channel].PitchBendSemiTones * 100 + Channel[channel].PitchBendHundreds; 699 } 700 break; 701 702 case MIDI_DATAENTRY_LSB: 703 if (Channel[channel].RPN == MIDI_PITCHBEND_LSB) 704 { 705 Channel[channel].PitchBendHundreds = data; 706 Channel[channel].PitchBendRange = Channel[channel].PitchBendSemiTones * 100 + Channel[channel].PitchBendHundreds; 707 } 708 break; 709 } 710 } 711 712 713 static void AL_ProgramChange(int const channel, int const patch) 714 { 715 // We only play channels 1 through 10 716 if (channel >= AL_MaxMidiChannel) 717 return; 718 719 Channel[channel].Timbre = patch; 720 } 721 722 723 static void AL_SetPitchBend(int const channel, int const lsb, int const msb) 724 { 725 // We only play channels 1 through 10 726 if (channel >= AL_MaxMidiChannel) 727 return; 728 729 int const pitchbend = lsb + (msb << 8); 730 int const TotalBend = pitchbend * Channel[channel].PitchBendRange / (PITCHBEND_CENTER / FINETUNE_RANGE); 731 732 Channel[channel].Pitchbend = pitchbend; 733 Channel[channel].KeyOffset = (int)(TotalBend / FINETUNE_RANGE); 734 Channel[channel].KeyOffset -= Channel[channel].PitchBendSemiTones; 735 736 Channel[channel].KeyDetune = (uint32_t)(TotalBend % FINETUNE_RANGE); 737 738 auto voice = Channel[channel].Voices.start; 739 while (voice != nullptr) 740 { 741 AL_SetVoicePitch(voice->num); 742 voice = voice->next; 743 } 744 } 745 746 747 static void AL_SetVolume(int volume) { AL_Volume = clamp(volume, 0, MIDI_MaxVolume); } 748 749 750 static void AL_Shutdown(void) 751 { 752 OPL3_Reset(&AL_Chip, MV_MixRate); 753 AL_Reset(); 754 AL_ResetVoices(); 755 } 756 757 758 static int AL_Init(void) 759 { 760 AL_Shutdown(); 761 AL_CalcPitchInfo(); 762 763 return AdLibErr_Ok; 764 } 765 766 767 void AL_RegisterTimbreBank(uint8_t *timbres) 768 { 769 for (int i = 0; i < 256; i++) 770 { 771 ADLIB_TimbreBank[i].SAVEK[0] = *(timbres++); 772 ADLIB_TimbreBank[i].SAVEK[1] = *(timbres++); 773 ADLIB_TimbreBank[i].Level[0] = *(timbres++); 774 ADLIB_TimbreBank[i].Level[1] = *(timbres++); 775 ADLIB_TimbreBank[i].Env1[0] = *(timbres++); 776 ADLIB_TimbreBank[i].Env1[1] = *(timbres++); 777 ADLIB_TimbreBank[i].Env2[0] = *(timbres++); 778 ADLIB_TimbreBank[i].Env2[1] = *(timbres++); 779 ADLIB_TimbreBank[i].Wave[0] = *(timbres++); 780 ADLIB_TimbreBank[i].Wave[1] = *(timbres++); 781 ADLIB_TimbreBank[i].Feedback = *(timbres++); 782 ADLIB_TimbreBank[i].Transpose = *(int8_t *)(timbres++); 783 ADLIB_TimbreBank[i].Velocity = *(int8_t *)(timbres++); 784 } 785 }