⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lkeymidi.cpp

📁 ldraw_DOS游戏开发包
💻 CPP
📖 第 1 页 / 共 4 页
字号:
      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 + -