?? lkeymidi.cpp
字號:
if (midi_waiting[c].note >= 0)
midi_note_on(midi_waiting[c].channel, midi_waiting[c].note,
midi_waiting[c].volume, 0);
midi_semaphore = FALSE;
}
char lmMidiStatus()
{ if (midifile) return 1;
return 0;
}
void lmMidiResume()
{ if (midifile==NULL||lmMidiFlag==0) return;
lt_install_int_ex(midi_player, midi_timer_speed);
}
static int load_patches(MIDI *midi)
{
char patches[128], drums[128];
unsigned char *p, *end;
unsigned char running_status, event;
long l;
int c;
for (c=0; c<128; c++) /* initialise to unused */
patches[c] = drums[c] = FALSE;
patches[0] = TRUE; /* always load the piano */
for (c=0; c<MIDI_TRACKS; c++) { /* for each track... */
p = midi->track[c].data;
end = p + midi->track[c].len;
running_status = 0;
while (p < end) { /* work through data stream */
event = *p;
if (event & 0x80) { /* regular message */
p++;
if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF))
running_status = event;
}
else /* use running status */
event = running_status;
switch (event>>4) {
case 0x0C: /* program change! */
patches[*p] = TRUE;
p++;
break;
case 0x09: /* note on, is it a drum? */
if ((event & 0x0F) == 9)
drums[*p] = TRUE;
p += 2;
break;
case 0x08: /* note off */
case 0x0A: /* note aftertouch */
case 0x0B: /* control change */
case 0x0E: /* pitch bend */
p += 2;
break;
case 0x0D: /* channel aftertouch */
p += 1;
break;
case 0x0F: /* special event */
switch (event) {
case 0xF0: /* sysex */
case 0xF7:
l = parse_var_len(&p);
p += l;
break;
case 0xF2: /* song position */
p += 2;
break;
case 0xF3: /* song select */
p++;
break;
case 0xFF: /* meta-event */
p++;
l = parse_var_len(&p);
p += l;
break;
default:
/* the other special events don't have any data bytes,
so we don't need to bother skipping past them */
break;
}
break;
default:
/* something has gone badly wrong if we ever get to here */
break;
}
if (p < end) /* skip time offset */
parse_var_len(&p);
}
}
/* tell the driver to do its stuff */
return midi_driver->load_patches(patches, drums);
}
int lmMidiPlay(MIDI *midi, int loop)
{
int c;
if (!lmMidiFlag) return -1;
lt_remove_int(midi_player);
for (c=0; c<16; c++)
all_notes_off(c);
if (midi) {
if (!midi_loaded_patches)
if (load_patches(midi) != 0)
return -1;
midi_loop = loop;
midi_loop_start = -1;
midi_loop_end = -1;
prepare_to_play(midi);
/* arbitrary speed, midi_player() will adjust it */
lt_install_int(midi_player, 20);
}
else {
midifile = NULL;
midi_pos = -1;
}
return 0;
}
/* midi_init:
* Sets up the MIDI player ready for use. Returns non-zero on failure.
*/
extern MIDI_DRIVER lmMidi_adlib;
static int midi_init(char driver)
{
int c, c2, c3;
int argc, back = 0;
char **argv;
char buf[16];
midi_loaded_patches = FALSE;
switch (driver)
{ case MIDI_AUTO: midi_driver = &lmMidi_adlib; break;
case MIDI_ADLIB: midi_driver = &lmMidi_adlib; break;
case MIDI_DIGI: sprintf(lsys_message,"Haven't supported digi midi\n");
back = 1; break;
default: back = 1;
}
if (back) return FALSE;
if (!midi_driver->detect()) {
sprintf(lsys_message,"MIDI detect failed\n");
return FALSE;
}
if (!midi_driver->init(64)) {
sprintf(lsys_message,"MIDI init failed\n");
return FALSE;
}
lt_install_timer();
for (c=0; c<16; c++) {
midi_channel[c].volume = 128;
midi_channel[c].pitch_bend = 0x2000;
for (c2=0; c2<128; c2++)
for (c3=0; c3<MIDI_LAYERS; c3++)
midi_channel[c].note[c2][c3] = -1;
}
for (c=0; c<MIDI_VOICES; c++) {
midi_voice[c].note = -1;
midi_voice[c].time = 0;
}
for (c=0; c<128; c++) {
sprintf(buf, "p%d", c+1);
argv=NULL;
if ((argv) && (argc == 4)) {
patch_table[c].bank1 = atoi(argv[0]);
patch_table[c].bank2 = atoi(argv[1]);
patch_table[c].prog = atoi(argv[2]);
patch_table[c].pitch = atoi(argv[3]);
}
else {
patch_table[c].bank1 = -1;
patch_table[c].bank2 = -1;
patch_table[c].prog = c;
patch_table[c].pitch = 0;
}
}
return TRUE;
}
static void midi_exit()
{
lmStopMidi();
midi_driver->exit();
}
static void prepare_to_play(MIDI *midi)
{
int c;
for (c=0; c<16; c++)
reset_controllers(c);
update_controllers();
midifile = midi;
midi_pos = 0;
midi_pos_counter = 0;
midi_speed = TIMERS_PER_SECOND / 2 / midifile->divisions; /* 120 bpm */
midi_new_speed = -1;
midi_pos_speed = midi_speed * midifile->divisions;
midi_timer_speed = 0;
midi_seeking = 0;
midi_looping = 0;
for (c=0; c<16; c++) {
midi_channel[c].patch = 0;
if (midi_driver->raw_midi)
raw_program_change(c, 0);
}
for (c=0; c<MIDI_TRACKS; c++) {
if (midi->track[c].data) {
midi_track[c].pos = midi->track[c].data;
midi_track[c].timer = parse_var_len(&midi_track[c].pos);
midi_track[c].timer *= midi_speed;
}
else {
midi_track[c].pos = NULL;
midi_track[c].timer = LONG_MAX;
}
midi_track[c].running_status = 0;
}
}
void ls_set_volume(int digi_volume,int midi_volume)
{ if (midi_volume >= 0) {
if (midi_volume<0) midi_volume=0;
if (midi_volume>255) midi_volume=255;
if ((midi_driver->mixer_volume) &&
(midi_driver->mixer_volume(midi_volume) == 0))
lm_midi_volume = -1;
else
lm_midi_volume = midi_volume;
}
if (digi_volume >= 0) {
}
}
/**************************************************************************
* LinDevelop v1.2
* The core FM MIDI
**************************************************************************/
#define TRUE 1
#define FALSE 0
/* external interface to the Adlib driver */
static int fm_detect();
static int fm_init(int voices);
static void fm_exit();
static int fm_mixer_volume(int volume);
static int fm_load_patches(char *patches, char *drums);
static void fm_key_on(int inst, int note, int bend, int vol, int pan);
static void fm_key_off(int voice);
static void fm_set_volume(int voice, int vol);
static void fm_set_pitch(int voice, int note, int bend);
void _dummy_adjust_patches(char *patches, char *drums) {}
void _dummy_noop2(int p1, int p2) {}
static char adlib_desc[80] = "not initialised";
MIDI_DRIVER lmMidi_adlib =
{
"Adlib",
adlib_desc,
0, 0, 0, 0, -1, -1,
fm_detect,
fm_init,
fm_exit,
NULL, /*fm_mixer_volume,*/
NULL,
fm_load_patches,
_dummy_adjust_patches,
fm_key_on,
fm_key_off,
fm_set_volume,
fm_set_pitch,
_dummy_noop2,
_dummy_noop2
};
typedef struct FM_INSTRUMENT
{
unsigned char characteristic1;
unsigned char characteristic2;
unsigned char level1;
unsigned char level2;
unsigned char attackdecay1;
unsigned char attackdecay2;
unsigned char sustainrelease1;
unsigned char sustainrelease2;
unsigned char wave1;
unsigned char wave2;
unsigned char feedback;
unsigned char freq;
unsigned char key;
unsigned char type;
} FM_INSTRUMENT;
#define FM_HH 1
#define FM_CY 2
#define FM_TT 4
#define FM_SD 8
#define FM_BD 16
/* include the GM patch set (static data) */
#include <source\lkeymmap.h>
/* is the OPL in percussion mode? */
static int fm_drum_mode = FALSE;
/* register offsets for each voice */
static int fm_offset[18] = {
0x000, 0x001, 0x002, 0x008, 0x009, 0x00A, 0x010, 0x011, 0x012,
0x100, 0x101, 0x102, 0x108, 0x109, 0x10A, 0x110, 0x111, 0x112
};
/* for converting midi note numbers to FM frequencies */
static int fm_freq[13] = {
0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA,
0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE
};
/* logarithmic relationship between midi and FM volumes */
static int fm_vol_table[128] = {
0, 11, 16, 19, 22, 25, 27, 29, 32, 33, 35, 37, 39, 40, 42, 43,
45, 46, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
64, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77,
78, 79, 80, 80, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 89, 89,
90, 91, 91, 92, 93, 93, 94, 95, 96, 96, 97, 97, 98, 99, 99, 100,
101, 101, 102, 103, 103, 104, 104, 105, 106, 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, 124, 124, 125, 125, 126, 126, 127
};
/* drum channel tables: BD SD TT CY HH */
static int fm_drum_channel[] = { 6, 7, 8, 8, 7 };
static int fm_drum_op1[] = { TRUE, FALSE, TRUE, FALSE, TRUE };
static int fm_drum_op2[] = { TRUE, TRUE, FALSE, TRUE, FALSE };
static int fm_drum_pitch[] = { TRUE, TRUE, TRUE, FALSE, FALSE };
/* cached information about the state of the drum channels */
static FM_INSTRUMENT *fm_drum_cached_inst1[5];
static FM_INSTRUMENT *fm_drum_cached_inst2[5];
static int fm_drum_cached_vol1[5];
static int fm_drum_cached_vol2[5];
static long fm_drum_cached_time[5];
/* various bits of information about the current state of the FM chip */
static unsigned char fm_drum_mask;
static unsigned char fm_key[18];
static unsigned char fm_keyscale[18];
static unsigned char fm_feedback[18];
static int fm_level[18];
static int fm_patch[18];
#define VOICE_OFFSET(x) ((x < 9) ? x : 0x100+x-9)
#define midi_adlib lmMidi_adlib
static midi_card = MIDI_OPL3;
int lm_volume_step = 8;
/* fm_reset:
* Resets the FM chip. If enable is set, puts OPL3 cards into OPL3 mode,
* otherwise puts them into OPL2 emulation mode.
*/
static void fm_reset(int enable)
{
int i;
for (i=0xF5; i>0; i--)
lsFMWrite(i, 0);
if (midi_card == MIDI_OPL3) { /* if we have an OPL3... */
lk_fm_delay1 = 1;
lk_fm_delay2 = 2;
lsFMWrite(0x105, 1); /* enable OPL3 mode */
for (i=0x1F5; i>0x105; i--)
lsFMWrite(i, 0);
for (i=0x104; i>0x100; i--)
lsFMWrite(i, 0);
if (!enable)
lsFMWrite(0x105, 0); /* turn OPL3 mode off again */
}
else {
lk_fm_delay1 = 6;
lk_fm_delay2 = 35;
if (midi_card == MIDI_2XOPL2) /* if we have a second OPL2... */
{
for (i=0x1F5; i>0x100; i--)
lsFMWrite(i, 0);
lsFMWrite(0x101, 0x20);
lsFMWrite(0x1BD, 0xC0);
}
}
for (i=0; i<midi_adlib.voices; i++) {
fm_key[i] = 0;
fm_keyscale[i] = 0;
fm_feedback[i] = 0;
fm_level[i] = 0;
fm_patch[i] = -1;
lsFMWrite(0x40+fm_offset[i], 63);
lsFMWrite(0x43+fm_offset[i], 63);
}
for (i=0; i<5; i++) {
fm_drum_cached_inst1[i] = NULL;
fm_drum_cached_inst2[i] = NULL;
fm_drum_cached_vol1[i] = -1;
fm_drum_cached_vol2[i] = -1;
fm_drum_cached_time[i] = 0;
}
lsFMWrite(0x01, 0x20); /* turn on wave form control */
fm_drum_mode = FALSE;
fm_drum_mask = 0xC0;
lsFMWrite(0xBD, fm_drum_mask); /* set AM and vibrato to high */
lmMidi_adlib.xmin = -1;
lmMidi_adlib.xmax = -1;
}
/* fm_set_drum_mode:
* Switches the OPL synth between normal and percussion modes.
*/
static void fm_set_drum_mode(int usedrums)
{
int i;
fm_drum_mode = usedrums;
fm_drum_mask = usedrums ? 0xE0 : 0xC0;
midi_adlib.xmin = usedrums ? 6 : -1;
midi_adlib.xmax = usedrums ? 8 : -1;
for (i=6; i<9; i++)
if (midi_card == MIDI_OPL3)
lsFMWrite(0xC0+VOICE_OFFSET(i), 0x30);
else
lsFMWrite(0xC0+VOICE_OFFSET(i), 0);
lsFMWrite(0xBD, fm_drum_mask);
}
/* fm_set_voice:
* Sets the sound to be used for the specified voice, from a structure
* containing eleven bytes of FM operator data. Note that it doesn't
* actually set the volume: it just stores volume data in the fm_level
* arrays for fm_set_volume() to use.
*/
static inline void fm_set_voice(int voice, FM_INSTRUMENT *inst)
{
/* store some info */
fm_keyscale[voice] = inst->level2 & 0xC0;
fm_level[voice] = 63 - (inst->level2 & 63);
fm_feedback[voice] = inst->feedback;
/* write the new data */
lsFMWrite(0x20+fm_offset[voice], inst->characteristic1);
lsFMWrite(0x23+fm_offset[voice], inst->characteristic2);
lsFMWrite(0x60+fm_offset[voice], inst->attackdecay1);
lsFMWrite(0x63+fm_offset[voice], inst->attackdecay2);
lsFMWrite(0x80+fm_offset[voice], inst->sustainrelease1);
lsFMWrite(0x83+fm_offset[voice], inst->sustainrelease2);
lsFMWrite(0xE0+fm_offset[voice], inst->wave1);
lsFMWrite(0xE3+fm_offset[voice], inst->wave2);
/* don't set operator1 level for additive synthesis sounds */
if (!(inst->feedback & 1))
lsFMWrite(0x40+fm_offset[voice], inst->level1);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -