974 lines
13 KiB
C++
974 lines
13 KiB
C++
//
|
|
// Copyright(C) 1993-1996 Id Software, Inc.
|
|
// Copyright(C) 2005-2014 Simon Howard
|
|
// Copyright(C) 2014-2015 Alexey Khokholov
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// DESCRIPTION:
|
|
// System interface for music.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include "../interface.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#define MIDI_CHANNELS_PER_TRACK 16
|
|
|
|
#define MIDI_EVENT_NOTE_OFF 0x80
|
|
#define MIDI_EVENT_NOTE_ON 0x90
|
|
|
|
#define MIDI_CONTROLLER_MAIN_VOLUME 0x7
|
|
#define MIDI_CONTROLLER_PAN 0xa
|
|
#define MIDI_CONTROLLER_ALL_NOTES_OFF 0x7b
|
|
#define MIDI_EVENT_CONTROLLER 0xb0
|
|
#define MIDI_EVENT_PROGRAM_CHANGE 0xc0
|
|
#define MIDI_EVENT_CHAN_AFTERTOUCH 0xd0
|
|
#define MIDI_EVENT_PITCH_BEND 0xe0
|
|
|
|
#define OPL_NUM_OPERATORS 21
|
|
#define OPL_NUM_VOICES 9
|
|
|
|
#define OPL_REG_WAVEFORM_ENABLE 0x01
|
|
#define OPL_REG_TIMER1 0x02
|
|
#define OPL_REG_TIMER2 0x03
|
|
#define OPL_REG_TIMER_CTRL 0x04
|
|
#define OPL_REG_FM_MODE 0x08
|
|
|
|
#define OPL_REGS_TREMOLO 0x20
|
|
#define OPL_REGS_LEVEL 0x40
|
|
#define OPL_REGS_ATTACK 0x60
|
|
#define OPL_REGS_SUSTAIN 0x80
|
|
#define OPL_REGS_WAVEFORM 0xE0
|
|
|
|
#define OPL_REGS_FREQ_1 0xA0
|
|
#define OPL_REGS_FREQ_2 0xB0
|
|
#define OPL_REGS_FEEDBACK 0xC0
|
|
|
|
#define OPL_REG_NEW_MODE 0x105
|
|
|
|
#define GENMIDI_NUM_INSTRS 128
|
|
#define GENMIDI_NUM_PERCUSSION 47
|
|
|
|
#define GENMIDI_HEADER "#OPL_II#"
|
|
#define GENMIDI_FLAG_FIXED 0x0001 /* fixed pitch */
|
|
#define GENMIDI_FLAG_2VOICE 0x0004 /* double voice (OPL3) */
|
|
|
|
#define PERCUSSION_LOG_LEN 16
|
|
|
|
typedef unsigned char byte;
|
|
|
|
#pragma pack(1)
|
|
typedef struct
|
|
{
|
|
byte tremolo;
|
|
byte attack;
|
|
byte sustain;
|
|
byte waveform;
|
|
byte scale;
|
|
byte level;
|
|
} genmidi_op_t;
|
|
#pragma pack()
|
|
|
|
#pragma pack(1)
|
|
typedef struct
|
|
{
|
|
genmidi_op_t modulator;
|
|
byte feedback;
|
|
genmidi_op_t carrier;
|
|
byte unused;
|
|
short base_note_offset;
|
|
} genmidi_voice_t;
|
|
#pragma pack()
|
|
|
|
#pragma pack(1)
|
|
typedef struct
|
|
{
|
|
unsigned short flags;
|
|
byte fine_tuning;
|
|
byte fixed_note;
|
|
|
|
genmidi_voice_t voices[2];
|
|
} genmidi_instr_t;
|
|
#pragma pack()
|
|
|
|
// Data associated with a channel of a track that is currently playing.
|
|
|
|
typedef struct
|
|
{
|
|
// The instrument currently used for this track.
|
|
|
|
const genmidi_instr_t *instrument;
|
|
|
|
// Volume level
|
|
|
|
int volume;
|
|
|
|
// Pan value
|
|
|
|
int pan, panex;
|
|
|
|
// Pitch bend value:
|
|
|
|
int bend;
|
|
|
|
} opl_channel_data_t;
|
|
|
|
typedef struct opl_voice_s opl_voice_t;
|
|
|
|
struct opl_voice_s {
|
|
// Index of this voice:
|
|
int index;
|
|
|
|
// The operators used by this voice:
|
|
int op1, op2;
|
|
|
|
// Array of this voice
|
|
int array;
|
|
|
|
// Currently-loaded instrument data
|
|
const genmidi_instr_t *current_instr;
|
|
|
|
// The voice number in the instrument to use.
|
|
// This is normally set to zero; if this is a double voice
|
|
// instrument, it may be one.
|
|
unsigned int current_instr_voice;
|
|
|
|
// The channel currently using this voice.
|
|
opl_channel_data_t *channel;
|
|
|
|
// The midi key that this voice is playing.
|
|
unsigned int key;
|
|
|
|
// The note being played. This is normally the same as
|
|
// the key, but if the instrument is a fixed pitch
|
|
// instrument, it is different.
|
|
unsigned int note;
|
|
|
|
// The frequency value being used.
|
|
unsigned int freq;
|
|
|
|
// The volume of the note being played on this channel.
|
|
unsigned int note_volume;
|
|
|
|
// The current volume (register value) that has been set for this channel.
|
|
unsigned int car_volume;
|
|
unsigned int mod_volume;
|
|
|
|
// The current pan.
|
|
unsigned int reg_pan;
|
|
|
|
// Priority.
|
|
unsigned int priority;
|
|
};
|
|
|
|
typedef enum {
|
|
opl_doom1_1_666, // Doom 1 v1.666
|
|
opl_doom2_1_666, // Doom 2 v1.666, Hexen, Heretic
|
|
opl_doom_1_9 // Doom v1.9, Strife
|
|
} opl_driver_ver_t;
|
|
|
|
// Operators used by the different voices.
|
|
|
|
const int voice_operators[2][OPL_NUM_VOICES] = {
|
|
{ 0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12 },
|
|
{ 0x03, 0x04, 0x05, 0x0b, 0x0c, 0x0d, 0x13, 0x14, 0x15 }
|
|
};
|
|
|
|
// Frequency values to use for each note.
|
|
|
|
const unsigned short frequency_curve[] = {
|
|
|
|
0x133,
|
|
0x133,
|
|
0x134,
|
|
0x134,
|
|
0x135,
|
|
0x136,
|
|
0x136,
|
|
0x137, // -1
|
|
0x137,
|
|
0x138,
|
|
0x138,
|
|
0x139,
|
|
0x139,
|
|
0x13a,
|
|
0x13b,
|
|
0x13b,
|
|
0x13c,
|
|
0x13c,
|
|
0x13d,
|
|
0x13d,
|
|
0x13e,
|
|
0x13f,
|
|
0x13f,
|
|
0x140,
|
|
0x140,
|
|
0x141,
|
|
0x142,
|
|
0x142,
|
|
0x143,
|
|
0x143,
|
|
0x144,
|
|
0x144,
|
|
|
|
0x145,
|
|
0x146,
|
|
0x146,
|
|
0x147,
|
|
0x147,
|
|
0x148,
|
|
0x149,
|
|
0x149, // -2
|
|
0x14a,
|
|
0x14a,
|
|
0x14b,
|
|
0x14c,
|
|
0x14c,
|
|
0x14d,
|
|
0x14d,
|
|
0x14e,
|
|
0x14f,
|
|
0x14f,
|
|
0x150,
|
|
0x150,
|
|
0x151,
|
|
0x152,
|
|
0x152,
|
|
0x153,
|
|
0x153,
|
|
0x154,
|
|
0x155,
|
|
0x155,
|
|
0x156,
|
|
0x157,
|
|
0x157,
|
|
0x158,
|
|
|
|
// These are used for the first seven MIDI note values:
|
|
|
|
0x158,
|
|
0x159,
|
|
0x15a,
|
|
0x15a,
|
|
0x15b,
|
|
0x15b,
|
|
0x15c,
|
|
0x15d, // 0
|
|
0x15d,
|
|
0x15e,
|
|
0x15f,
|
|
0x15f,
|
|
0x160,
|
|
0x161,
|
|
0x161,
|
|
0x162,
|
|
0x162,
|
|
0x163,
|
|
0x164,
|
|
0x164,
|
|
0x165,
|
|
0x166,
|
|
0x166,
|
|
0x167,
|
|
0x168,
|
|
0x168,
|
|
0x169,
|
|
0x16a,
|
|
0x16a,
|
|
0x16b,
|
|
0x16c,
|
|
0x16c,
|
|
|
|
0x16d,
|
|
0x16e,
|
|
0x16e,
|
|
0x16f,
|
|
0x170,
|
|
0x170,
|
|
0x171,
|
|
0x172, // 1
|
|
0x172,
|
|
0x173,
|
|
0x174,
|
|
0x174,
|
|
0x175,
|
|
0x176,
|
|
0x176,
|
|
0x177,
|
|
0x178,
|
|
0x178,
|
|
0x179,
|
|
0x17a,
|
|
0x17a,
|
|
0x17b,
|
|
0x17c,
|
|
0x17c,
|
|
0x17d,
|
|
0x17e,
|
|
0x17e,
|
|
0x17f,
|
|
0x180,
|
|
0x181,
|
|
0x181,
|
|
0x182,
|
|
|
|
0x183,
|
|
0x183,
|
|
0x184,
|
|
0x185,
|
|
0x185,
|
|
0x186,
|
|
0x187,
|
|
0x188, // 2
|
|
0x188,
|
|
0x189,
|
|
0x18a,
|
|
0x18a,
|
|
0x18b,
|
|
0x18c,
|
|
0x18d,
|
|
0x18d,
|
|
0x18e,
|
|
0x18f,
|
|
0x18f,
|
|
0x190,
|
|
0x191,
|
|
0x192,
|
|
0x192,
|
|
0x193,
|
|
0x194,
|
|
0x194,
|
|
0x195,
|
|
0x196,
|
|
0x197,
|
|
0x197,
|
|
0x198,
|
|
0x199,
|
|
|
|
0x19a,
|
|
0x19a,
|
|
0x19b,
|
|
0x19c,
|
|
0x19d,
|
|
0x19d,
|
|
0x19e,
|
|
0x19f, // 3
|
|
0x1a0,
|
|
0x1a0,
|
|
0x1a1,
|
|
0x1a2,
|
|
0x1a3,
|
|
0x1a3,
|
|
0x1a4,
|
|
0x1a5,
|
|
0x1a6,
|
|
0x1a6,
|
|
0x1a7,
|
|
0x1a8,
|
|
0x1a9,
|
|
0x1a9,
|
|
0x1aa,
|
|
0x1ab,
|
|
0x1ac,
|
|
0x1ad,
|
|
0x1ad,
|
|
0x1ae,
|
|
0x1af,
|
|
0x1b0,
|
|
0x1b0,
|
|
0x1b1,
|
|
|
|
0x1b2,
|
|
0x1b3,
|
|
0x1b4,
|
|
0x1b4,
|
|
0x1b5,
|
|
0x1b6,
|
|
0x1b7,
|
|
0x1b8, // 4
|
|
0x1b8,
|
|
0x1b9,
|
|
0x1ba,
|
|
0x1bb,
|
|
0x1bc,
|
|
0x1bc,
|
|
0x1bd,
|
|
0x1be,
|
|
0x1bf,
|
|
0x1c0,
|
|
0x1c0,
|
|
0x1c1,
|
|
0x1c2,
|
|
0x1c3,
|
|
0x1c4,
|
|
0x1c4,
|
|
0x1c5,
|
|
0x1c6,
|
|
0x1c7,
|
|
0x1c8,
|
|
0x1c9,
|
|
0x1c9,
|
|
0x1ca,
|
|
0x1cb,
|
|
|
|
0x1cc,
|
|
0x1cd,
|
|
0x1ce,
|
|
0x1ce,
|
|
0x1cf,
|
|
0x1d0,
|
|
0x1d1,
|
|
0x1d2, // 5
|
|
0x1d3,
|
|
0x1d3,
|
|
0x1d4,
|
|
0x1d5,
|
|
0x1d6,
|
|
0x1d7,
|
|
0x1d8,
|
|
0x1d8,
|
|
0x1d9,
|
|
0x1da,
|
|
0x1db,
|
|
0x1dc,
|
|
0x1dd,
|
|
0x1de,
|
|
0x1de,
|
|
0x1df,
|
|
0x1e0,
|
|
0x1e1,
|
|
0x1e2,
|
|
0x1e3,
|
|
0x1e4,
|
|
0x1e5,
|
|
0x1e5,
|
|
0x1e6,
|
|
|
|
0x1e7,
|
|
0x1e8,
|
|
0x1e9,
|
|
0x1ea,
|
|
0x1eb,
|
|
0x1ec,
|
|
0x1ed,
|
|
0x1ed, // 6
|
|
0x1ee,
|
|
0x1ef,
|
|
0x1f0,
|
|
0x1f1,
|
|
0x1f2,
|
|
0x1f3,
|
|
0x1f4,
|
|
0x1f5,
|
|
0x1f6,
|
|
0x1f6,
|
|
0x1f7,
|
|
0x1f8,
|
|
0x1f9,
|
|
0x1fa,
|
|
0x1fb,
|
|
0x1fc,
|
|
0x1fd,
|
|
0x1fe,
|
|
0x1ff,
|
|
0x200,
|
|
0x201,
|
|
0x201,
|
|
0x202,
|
|
0x203,
|
|
|
|
// First note of looped range used for all octaves:
|
|
|
|
0x204,
|
|
0x205,
|
|
0x206,
|
|
0x207,
|
|
0x208,
|
|
0x209,
|
|
0x20a,
|
|
0x20b, // 7
|
|
0x20c,
|
|
0x20d,
|
|
0x20e,
|
|
0x20f,
|
|
0x210,
|
|
0x210,
|
|
0x211,
|
|
0x212,
|
|
0x213,
|
|
0x214,
|
|
0x215,
|
|
0x216,
|
|
0x217,
|
|
0x218,
|
|
0x219,
|
|
0x21a,
|
|
0x21b,
|
|
0x21c,
|
|
0x21d,
|
|
0x21e,
|
|
0x21f,
|
|
0x220,
|
|
0x221,
|
|
0x222,
|
|
|
|
0x223,
|
|
0x224,
|
|
0x225,
|
|
0x226,
|
|
0x227,
|
|
0x228,
|
|
0x229,
|
|
0x22a, // 8
|
|
0x22b,
|
|
0x22c,
|
|
0x22d,
|
|
0x22e,
|
|
0x22f,
|
|
0x230,
|
|
0x231,
|
|
0x232,
|
|
0x233,
|
|
0x234,
|
|
0x235,
|
|
0x236,
|
|
0x237,
|
|
0x238,
|
|
0x239,
|
|
0x23a,
|
|
0x23b,
|
|
0x23c,
|
|
0x23d,
|
|
0x23e,
|
|
0x23f,
|
|
0x240,
|
|
0x241,
|
|
0x242,
|
|
|
|
0x244,
|
|
0x245,
|
|
0x246,
|
|
0x247,
|
|
0x248,
|
|
0x249,
|
|
0x24a,
|
|
0x24b, // 9
|
|
0x24c,
|
|
0x24d,
|
|
0x24e,
|
|
0x24f,
|
|
0x250,
|
|
0x251,
|
|
0x252,
|
|
0x253,
|
|
0x254,
|
|
0x256,
|
|
0x257,
|
|
0x258,
|
|
0x259,
|
|
0x25a,
|
|
0x25b,
|
|
0x25c,
|
|
0x25d,
|
|
0x25e,
|
|
0x25f,
|
|
0x260,
|
|
0x262,
|
|
0x263,
|
|
0x264,
|
|
0x265,
|
|
|
|
0x266,
|
|
0x267,
|
|
0x268,
|
|
0x269,
|
|
0x26a,
|
|
0x26c,
|
|
0x26d,
|
|
0x26e, // 10
|
|
0x26f,
|
|
0x270,
|
|
0x271,
|
|
0x272,
|
|
0x273,
|
|
0x275,
|
|
0x276,
|
|
0x277,
|
|
0x278,
|
|
0x279,
|
|
0x27a,
|
|
0x27b,
|
|
0x27d,
|
|
0x27e,
|
|
0x27f,
|
|
0x280,
|
|
0x281,
|
|
0x282,
|
|
0x284,
|
|
0x285,
|
|
0x286,
|
|
0x287,
|
|
0x288,
|
|
0x289,
|
|
|
|
0x28b,
|
|
0x28c,
|
|
0x28d,
|
|
0x28e,
|
|
0x28f,
|
|
0x290,
|
|
0x292,
|
|
0x293, // 11
|
|
0x294,
|
|
0x295,
|
|
0x296,
|
|
0x298,
|
|
0x299,
|
|
0x29a,
|
|
0x29b,
|
|
0x29c,
|
|
0x29e,
|
|
0x29f,
|
|
0x2a0,
|
|
0x2a1,
|
|
0x2a2,
|
|
0x2a4,
|
|
0x2a5,
|
|
0x2a6,
|
|
0x2a7,
|
|
0x2a9,
|
|
0x2aa,
|
|
0x2ab,
|
|
0x2ac,
|
|
0x2ae,
|
|
0x2af,
|
|
0x2b0,
|
|
|
|
0x2b1,
|
|
0x2b2,
|
|
0x2b4,
|
|
0x2b5,
|
|
0x2b6,
|
|
0x2b7,
|
|
0x2b9,
|
|
0x2ba, // 12
|
|
0x2bb,
|
|
0x2bd,
|
|
0x2be,
|
|
0x2bf,
|
|
0x2c0,
|
|
0x2c2,
|
|
0x2c3,
|
|
0x2c4,
|
|
0x2c5,
|
|
0x2c7,
|
|
0x2c8,
|
|
0x2c9,
|
|
0x2cb,
|
|
0x2cc,
|
|
0x2cd,
|
|
0x2ce,
|
|
0x2d0,
|
|
0x2d1,
|
|
0x2d2,
|
|
0x2d4,
|
|
0x2d5,
|
|
0x2d6,
|
|
0x2d8,
|
|
0x2d9,
|
|
|
|
0x2da,
|
|
0x2dc,
|
|
0x2dd,
|
|
0x2de,
|
|
0x2e0,
|
|
0x2e1,
|
|
0x2e2,
|
|
0x2e4, // 13
|
|
0x2e5,
|
|
0x2e6,
|
|
0x2e8,
|
|
0x2e9,
|
|
0x2ea,
|
|
0x2ec,
|
|
0x2ed,
|
|
0x2ee,
|
|
0x2f0,
|
|
0x2f1,
|
|
0x2f2,
|
|
0x2f4,
|
|
0x2f5,
|
|
0x2f6,
|
|
0x2f8,
|
|
0x2f9,
|
|
0x2fb,
|
|
0x2fc,
|
|
0x2fd,
|
|
0x2ff,
|
|
0x300,
|
|
0x302,
|
|
0x303,
|
|
0x304,
|
|
|
|
0x306,
|
|
0x307,
|
|
0x309,
|
|
0x30a,
|
|
0x30b,
|
|
0x30d,
|
|
0x30e,
|
|
0x310, // 14
|
|
0x311,
|
|
0x312,
|
|
0x314,
|
|
0x315,
|
|
0x317,
|
|
0x318,
|
|
0x31a,
|
|
0x31b,
|
|
0x31c,
|
|
0x31e,
|
|
0x31f,
|
|
0x321,
|
|
0x322,
|
|
0x324,
|
|
0x325,
|
|
0x327,
|
|
0x328,
|
|
0x329,
|
|
0x32b,
|
|
0x32c,
|
|
0x32e,
|
|
0x32f,
|
|
0x331,
|
|
0x332,
|
|
|
|
0x334,
|
|
0x335,
|
|
0x337,
|
|
0x338,
|
|
0x33a,
|
|
0x33b,
|
|
0x33d,
|
|
0x33e, // 15
|
|
0x340,
|
|
0x341,
|
|
0x343,
|
|
0x344,
|
|
0x346,
|
|
0x347,
|
|
0x349,
|
|
0x34a,
|
|
0x34c,
|
|
0x34d,
|
|
0x34f,
|
|
0x350,
|
|
0x352,
|
|
0x353,
|
|
0x355,
|
|
0x357,
|
|
0x358,
|
|
0x35a,
|
|
0x35b,
|
|
0x35d,
|
|
0x35e,
|
|
0x360,
|
|
0x361,
|
|
0x363,
|
|
|
|
0x365,
|
|
0x366,
|
|
0x368,
|
|
0x369,
|
|
0x36b,
|
|
0x36c,
|
|
0x36e,
|
|
0x370, // 16
|
|
0x371,
|
|
0x373,
|
|
0x374,
|
|
0x376,
|
|
0x378,
|
|
0x379,
|
|
0x37b,
|
|
0x37c,
|
|
0x37e,
|
|
0x380,
|
|
0x381,
|
|
0x383,
|
|
0x384,
|
|
0x386,
|
|
0x388,
|
|
0x389,
|
|
0x38b,
|
|
0x38d,
|
|
0x38e,
|
|
0x390,
|
|
0x392,
|
|
0x393,
|
|
0x395,
|
|
0x397,
|
|
|
|
0x398,
|
|
0x39a,
|
|
0x39c,
|
|
0x39d,
|
|
0x39f,
|
|
0x3a1,
|
|
0x3a2,
|
|
0x3a4, // 17
|
|
0x3a6,
|
|
0x3a7,
|
|
0x3a9,
|
|
0x3ab,
|
|
0x3ac,
|
|
0x3ae,
|
|
0x3b0,
|
|
0x3b1,
|
|
0x3b3,
|
|
0x3b5,
|
|
0x3b7,
|
|
0x3b8,
|
|
0x3ba,
|
|
0x3bc,
|
|
0x3bd,
|
|
0x3bf,
|
|
0x3c1,
|
|
0x3c3,
|
|
0x3c4,
|
|
0x3c6,
|
|
0x3c8,
|
|
0x3ca,
|
|
0x3cb,
|
|
0x3cd,
|
|
|
|
// The last note has an incomplete range, and loops round back to
|
|
// the start. Note that the last value is actually a buffer overrun
|
|
// and does not fit with the other values.
|
|
|
|
0x3cf,
|
|
0x3d1,
|
|
0x3d2,
|
|
0x3d4,
|
|
0x3d6,
|
|
0x3d8,
|
|
0x3da,
|
|
0x3db, // 18
|
|
0x3dd,
|
|
0x3df,
|
|
0x3e1,
|
|
0x3e3,
|
|
0x3e4,
|
|
0x3e6,
|
|
0x3e8,
|
|
0x3ea,
|
|
0x3ec,
|
|
0x3ed,
|
|
0x3ef,
|
|
0x3f1,
|
|
0x3f3,
|
|
0x3f5,
|
|
0x3f6,
|
|
0x3f8,
|
|
0x3fa,
|
|
0x3fc,
|
|
0x3fe,
|
|
0x36c,
|
|
};
|
|
|
|
// Mapping from MIDI volume level to OPL level value.
|
|
|
|
const unsigned int volume_mapping_table[] = {
|
|
0, 1, 3, 5, 6, 8, 10, 11,
|
|
13, 14, 16, 17, 19, 20, 22, 23,
|
|
25, 26, 27, 29, 30, 32, 33, 34,
|
|
36, 37, 39, 41, 43, 45, 47, 49,
|
|
50, 52, 54, 55, 57, 59, 60, 61,
|
|
63, 64, 66, 67, 68, 69, 71, 72,
|
|
73, 74, 75, 76, 77, 79, 80, 81,
|
|
82, 83, 84, 84, 85, 86, 87, 88,
|
|
89, 90, 91, 92, 92, 93, 94, 95,
|
|
96, 96, 97, 98, 99, 99, 100, 101,
|
|
101, 102, 103, 103, 104, 105, 105, 106,
|
|
107, 107, 108, 109, 109, 110, 110, 111,
|
|
112, 112, 113, 113, 114, 114, 115, 115,
|
|
116, 117, 117, 118, 118, 119, 119, 120,
|
|
120, 121, 121, 122, 122, 123, 123, 123,
|
|
124, 124, 125, 125, 126, 126, 127, 127
|
|
};
|
|
|
|
const unsigned int channel_map_table[MIDI_CHANNELS_PER_TRACK] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 15, 9, 10, 11, 12, 13, 14
|
|
};
|
|
|
|
class DoomOPL : public midisynth {
|
|
private:
|
|
fm_chip *opl;
|
|
opl_channel_data_t channels[MIDI_CHANNELS_PER_TRACK];
|
|
opl_driver_ver_t opl_drv_ver = opl_doom_1_9;
|
|
|
|
// GENMIDI lump instrument data:
|
|
|
|
const genmidi_instr_t *main_instrs;
|
|
const genmidi_instr_t *percussion_instrs;
|
|
|
|
// Voices:
|
|
|
|
opl_voice_t voices[OPL_NUM_VOICES * 2];
|
|
opl_voice_t *voice_free_list[OPL_NUM_VOICES * 2];
|
|
opl_voice_t *voice_alloced_list[OPL_NUM_VOICES * 2];
|
|
unsigned int voice_free_num = 0;
|
|
unsigned int voice_alloced_num = 0;
|
|
|
|
bool opl_new;
|
|
bool opl_extp;
|
|
unsigned int opl_voices;
|
|
|
|
void OPL_WriteRegister(unsigned int reg, unsigned char data);
|
|
void OPL_InitRegisters(bool opl_new);
|
|
bool LoadInstrumentTable(unsigned int bank);
|
|
void ReleaseVoice(unsigned int id);
|
|
void LoadOperatorData(int slot, const genmidi_op_t *data, bool max_level, unsigned int *volume);
|
|
void SetVoiceInstrument(opl_voice_t *voice, const genmidi_instr_t *instr, unsigned int instr_voice);
|
|
void SetVoiceVolume(opl_voice_t *voice, unsigned int volume);
|
|
void SetVoicePan(opl_voice_t *voice, unsigned int pan);
|
|
void SetVoicePanEx(opl_voice_t *voice, unsigned int pan);
|
|
void InitVoices(void);
|
|
void VoiceKeyOff(opl_voice_t *voice);
|
|
opl_channel_data_t *TrackChannelForEvent(unsigned char channel_num);
|
|
void KeyOffEvent(unsigned char channel_num, unsigned char key);
|
|
void ReplaceExistingVoice();
|
|
void ReplaceExistingVoiceDoom1();
|
|
void ReplaceExistingVoiceDoom2(opl_channel_data_t *channel);
|
|
unsigned int FrequencyForVoice(opl_voice_t *voice);
|
|
void UpdateVoiceFrequency(opl_voice_t *voice);
|
|
void VoiceKeyOn(opl_channel_data_t *channel, const genmidi_instr_t *instrument, unsigned int instrument_voice,
|
|
unsigned int note, unsigned int key, unsigned int volume);
|
|
void KeyOnEvent(unsigned char channel_num, unsigned char key, unsigned char volume);
|
|
void ProgramChangeEvent(unsigned char channel_num, unsigned char instrument);
|
|
void SetChannelVolume(opl_channel_data_t *channel, unsigned int volume);
|
|
void SetChannelPan(opl_channel_data_t *channel, unsigned int pan);
|
|
void AllNotesOff(opl_channel_data_t *channel, unsigned int param);
|
|
void ControllerEvent(unsigned char channel_num, unsigned char controller, unsigned char param);
|
|
void PitchBendEvent(unsigned char channel_num, unsigned char bend);
|
|
void InitChannel(opl_channel_data_t *channel);
|
|
|
|
public:
|
|
const char *midi_synth_name(void);
|
|
unsigned int midi_bank_count(void);
|
|
const char *midi_bank_name(unsigned int bank);
|
|
int midi_init(unsigned int rate, unsigned int bank, unsigned int extp);
|
|
void midi_write(unsigned int data);
|
|
void midi_generate(signed short *buffer, unsigned int length);
|
|
};
|