home *** CD-ROM | disk | FTP | other *** search
/ HomeWare 14 / HOMEWARE14.bin / music / vaisdk.arj / NOTE.C < prev    next >
C/C++ Source or Header  |  1994-04-10  |  24KB  |  1,040 lines

  1.  
  2. ;   /*\
  3. ;---|*|----====< Play MIDI >====----
  4. ;---|*|
  5. ;---|*| play/record blocks of MIDI
  6. ;---|*|
  7. ;---|*| Copyright (c) 1993,1994  V.E.S.A, Inc. All Rights Reserved.
  8. ;---|*|
  9. ;---|*| VBE/AI 1.0 Specification
  10. ;---|*|    February 2, 1994. 1.00 release
  11. ;---|*|
  12. ;   \*/
  13.  
  14. #include <stdio.h>
  15. #include <signal.h>
  16.  
  17. #include "vbeai.h"
  18. #include "vesa.h"
  19. #include "midi.h"
  20.  
  21. #define TRUE    -1
  22. #define FALSE    0
  23. #define ON      TRUE
  24. #define OFF     FALSE
  25.  
  26.  
  27. ;   /*\
  28. ;---|*| External Variables
  29. ;   \*/
  30.  
  31.         extern char *melodicnames[];
  32.         extern char *percussivenames[];
  33.  
  34.  
  35. ;   /*\
  36. ;---|*| Global Variables
  37. ;   \*/
  38.  
  39.         VESAHANDLE hMIDI  = 0;
  40.  
  41.         GeneralDeviceClass gdc; // receives a copy of the VESA driver info block
  42.         fpMIDServ msv;          // pointer to wave functions
  43.  
  44.  
  45. ;   /*\
  46. ;---|*| prototypes
  47. ;   \*/
  48.  
  49.         long readvalue              ( );
  50.         long GetValue               ( char *,long );
  51.         VESAHANDLE OpenTheDriver    ( int );
  52.  
  53.         char far *memptr = 0;
  54.         char far *pptr;         // patch pointer
  55.  
  56.         char notes[16] = {0};
  57.         int  patch     = 0x01;
  58.         int  channel   = 0x01;
  59.         int  UserPref  = 0;
  60.         int  AutoNoteOff = TRUE;
  61.  
  62.         void far pascal OurMIDIReceiver   ( int, int, char, long );
  63.         void far pascal OurFreeCBCallBack ( int, int, void far *, long );
  64.  
  65.         int  DelayTimer ( int, int );
  66.  
  67. #define DN_LOADPATCH    0x01
  68. #define DN_NOTEOFF      0x40
  69. #define DN_NOTEON       0x30
  70. #define DN_PITCHUP      0x04
  71. #define DN_PITCHDN      0x05
  72. #define DN_PITCHCNTR    0x06
  73. #define DN_VELUP        0x07
  74. #define DN_VELDOWN      0x08
  75. #define DN_ERRORCHK     0xEE
  76.  
  77.         int DoNote(int);
  78.  
  79.  
  80. ;   /*\
  81. ;---|*|------------------==============================-------------------
  82. ;---|*|------------------====< Start of execution >====-------------------
  83. ;---|*|------------------==============================-------------------
  84. ;   \*/
  85.  
  86. main(argc,argv)
  87.     int argc;
  88.     char *argv[];
  89. {
  90. int c;
  91. int loop = -1;
  92. int noteison[10];
  93. int n;
  94.  
  95.     // process the command line
  96.  
  97.         CommandLine (argc,argv);
  98.  
  99.     // disable the ^C so the devices will close properly.
  100.  
  101.         signal (SIGINT,SIG_IGN);
  102.  
  103.     // Find one MIDI device
  104.  
  105.         if (!OpenTheDriver(UserPref)) { // get the driver the user prefer
  106.             printf ("Cannot find any installed VBE/AI devices!\n");
  107.             DoExit(-1);
  108.         }
  109.  
  110.     // process each note
  111.  
  112.         patch = -1;
  113.         while (1) {
  114.  
  115.             if (patch == -1)
  116.                 GetChannel();
  117.  
  118.             if (channel == -1)
  119.                 break;
  120.  
  121.             GetNote();
  122.  
  123.             if (patch == -1)
  124.                 continue;
  125.  
  126.             printf ("Loading patch %d on channel %d\n",patch,channel);
  127.  
  128.             if (!DoNote(DN_LOADPATCH))  // load  the patch
  129.                 break;
  130.  
  131.             // process a few commands
  132.  
  133.                 for (n=0;n<10;n++)
  134.                     noteison[n] = FALSE;
  135.  
  136.                 loop = -1;
  137.                 while (loop) {
  138.  
  139.                     printf ("   (P)lay (O)ff :  \b\b");
  140.                     while (!kbhit()) ;
  141.  
  142.                     if ((c = getch()) == 0)
  143.                         c = getch();
  144.  
  145.                     printf ("%c\r",c);
  146.  
  147.                     switch (c) {
  148.  
  149.                         case '1':
  150.                         case '2':
  151.                         case '3':
  152.                         case '4':
  153.                         case '5':
  154.                         case '6':
  155.                         case '7':
  156.                         case '8':
  157.                         case '9':
  158.                         case '0':
  159.                             if (c == '0')
  160.                                 c = 0x3A;
  161.  
  162.                             n = c - 0x31;
  163.                             if (noteison[n] && AutoNoteOff)
  164.                                 DoNote(DN_NOTEOFF+n);
  165.  
  166.                             DoNote(DN_NOTEON+n);
  167.                             noteison[n] = TRUE;
  168.                             break;
  169.  
  170.                         case '-':
  171.                             if (noteison[0] && AutoNoteOff)
  172.                                 DoNote(DN_NOTEOFF);
  173.                             DoNote(DN_VELDOWN);
  174.                             noteison[0] = TRUE;
  175.                             break;
  176.  
  177.                         case '+':
  178.                             if (noteison[0] && AutoNoteOff)
  179.                                 DoNote(DN_NOTEOFF);
  180.                             DoNote(DN_VELUP);
  181.                             noteison[0] = TRUE;
  182.                             break;
  183.  
  184.                         case 'p':
  185.                         case 'P':
  186.  
  187.                             if (noteison[0] && AutoNoteOff)
  188.                                 DoNote(DN_NOTEOFF);
  189.                             DoNote(DN_NOTEON);
  190.                             noteison[0] = TRUE;
  191.                             break;
  192.  
  193.                         case 'u':
  194.                         case 'U':
  195.                             DoNote(DN_PITCHUP);
  196.                             break;
  197.  
  198.                         case 'd':
  199.                         case 'D':
  200.                             DoNote(DN_PITCHDN);
  201.                             break;
  202.  
  203.                         case 'c':
  204.                         case 'C':
  205.                             DoNote(DN_PITCHCNTR);
  206.                             break;
  207.  
  208.                         default:
  209.                         case 'n':
  210.                         case 'N':
  211.                         case 'o':
  212.                         case 'O':
  213.  
  214.                             for (n=0;n<10;n++) {
  215.                                 if (noteison[n] && AutoNoteOff) {
  216.                                     DoNote(DN_NOTEOFF+n);
  217.                                     noteison[n] = FALSE;
  218.                                 }
  219.                             }
  220.  
  221.                             if ((c & 0x5f) != 'O')
  222.                                 loop = 0;
  223.  
  224.                             break;
  225.                     }
  226.                 }
  227.         }
  228.  
  229.     // exit now...
  230.  
  231.         DoExit(0);
  232. }
  233.  
  234. ;   /*\
  235. ;---|*|----------------------=======================----------------------
  236. ;---|*|----------------------====< Subroutines >====----------------------
  237. ;---|*|----------------------=======================----------------------
  238. ;   \*/
  239.  
  240. ;   /*\
  241. ;---|*|----====< BombOut >====----
  242. ;---|*|
  243. ;---|*| Give the error #, then bomb out...
  244. ;---|*|
  245. ;   \*/
  246.  
  247. BombOut(cc)
  248.     int cc;
  249. {
  250.  
  251.     // give a message
  252.  
  253.         printf ("Bombing out! code = %d\n",cc);
  254.         DoExit (cc);
  255. }
  256.  
  257. ;   /*\
  258. ;---|*|----====< buildstr >====----
  259. ;---|*|
  260. ;---|*| Build the string of instrument names
  261. ;---|*|
  262. ;   \*/
  263.  
  264. buildstr(t,n0,n1,n2,n3)
  265.     char *t;
  266.     int n0,n1,n2,n3;
  267. {
  268. char *trg,*src;
  269. int n;
  270.  
  271.     // blank fill the string
  272.  
  273.         trg=t;
  274.         for (n=0;n<79;n++)
  275.             *trg++ = ' ';
  276.         *trg = 0;
  277.  
  278.     // add each string name to the padded string
  279.  
  280.         src = (channel == 10) ? percussivenames[n0] : melodicnames[n0];
  281.         for(n=0;n<19;n++) {
  282.             if (*src == 0) break;
  283.             t[n] = *src++;
  284.         }
  285.  
  286.         src = (channel == 10) ? percussivenames[n1] : melodicnames[n1];
  287.         for(n=20;n<39;n++) {
  288.             if (*src ==0) break;
  289.             t[n] = *src++;
  290.         }
  291.  
  292.         src = (channel == 10) ? percussivenames[n2] : melodicnames[n2];
  293.         for(n=40;n<59;n++) {
  294.             if (*src ==0) break;
  295.             t[n] = *src++;
  296.         }
  297.  
  298.         src = (channel == 10) ? percussivenames[n3] : melodicnames[n3];
  299.         for(n=60;n<78;n++) {
  300.             if (*src ==0) break;
  301.             t[n] = *src++;
  302.         }
  303.  
  304.         t[78] = '\n';
  305. }
  306.  
  307. ;
  308. ;   /*\
  309. ;---|*|----====< ChannelHelps >====----
  310. ;---|*|
  311. ;---|*| Give the user the commandline option list
  312. ;---|*|
  313. ;   \*/
  314.  
  315. ChannelHelps()
  316. {
  317. int n;
  318.  
  319.     // just print the helps
  320.  
  321.         printf ("\n");
  322.         printf ("Channels 1 - 9 and 11 - 16 are melodic. Channel 10 is percussive.\n");
  323.         printf ("\n");
  324.  
  325. }
  326.  
  327. ;
  328. ;   /*\
  329. ;---|*|----====< CommandLine >====----
  330. ;---|*|
  331. ;---|*| Process the command line switches
  332. ;---|*|
  333. ;   \*/
  334. CommandLine(argc,argv)
  335.     int argc;
  336.     char *argv[];
  337. {
  338. int n,x;
  339. char *s,c;
  340.  
  341.         GiveHelps();
  342.  
  343.         n = 1;
  344.         while (n<argc) {
  345.  
  346.             s = argv[n++];
  347.  
  348.             if (*s == '-') s++;
  349.             if (*s == '/') s++;
  350.  
  351.             switch (*s & 0xDF) {
  352.  
  353.                 case 'A':
  354.                     AutoNoteOff = FALSE;
  355.                     printf ("Notes will not automatically turn off.\n");
  356.                     break;
  357.  
  358.                 case 'P':
  359.                     UserPref = (int)GetValue (++s,0);
  360.                     printf ("User Prefers (%d) level drivers\n",UserPref);
  361.                     break;
  362.  
  363.                 default:
  364.                     printf ("Unknown option - %s\n",s);
  365.             }
  366.         }
  367.  
  368.     // separate the parameter text from the rest of the report
  369.  
  370.         printf ("\n");
  371. }
  372.  
  373. ;
  374. ;   /*\
  375. ;---|*|----====< DelayTimer >====----
  376. ;---|*|
  377. ;---|*| Delay this many clock ticks
  378. ;---|*|
  379. ;   \*/
  380.  
  381. DelayTimer(ticks,earlyout)
  382.     int ticks;
  383.     int earlyout;
  384. {
  385. int timer = -1;
  386. int delta = -1;
  387.  
  388.     // while we have time to waste...
  389.  
  390.         sysclocktic();
  391.  
  392.         while (ticks) {
  393.  
  394.             // watch the keyboard for an exit command
  395.  
  396.                 if (earlyout) {
  397.                     if (kbhit())
  398.                         if (getch() == 0x1b)
  399.                             DoExit(-1);
  400.                 }
  401.  
  402.             // if the clock ticked, count down one...
  403.  
  404.                 if (sysclocktic())
  405.                     ticks--;
  406.  
  407.         }
  408. }
  409.  
  410. ;
  411. ;   /*\
  412. ;---|*|----====< DoNote >====----
  413. ;---|*|
  414. ;---|*| Process a keystroke into a note/pgm change
  415. ;---|*|
  416. ;   \*/
  417.  
  418. DoNote (c)
  419.     int c;
  420. {
  421. int len;
  422. VAIDhdr far *ph;
  423. OPL2native far *pt;
  424.  
  425. static unsigned char dmsg[3] = { 0x90, 60, 0x7F };
  426. static unsigned char pchg[2] = { 0xE0, 0x00 };
  427. static unsigned char bend[3] = { 0xE0, 0x00, 0x40 };
  428.  
  429.         switch (c) {
  430.  
  431.             case DN_VELDOWN:
  432.  
  433.                 // adjust the velocity, then send the note ON
  434.  
  435.                 dmsg[2] -= 0x10;
  436.                 if (dmsg[2] > 0x7F)
  437.                     dmsg[2] = 0;
  438.  
  439.                 dmsg[1] = (channel == 10) ? patch-1 : 60;
  440.                 dmsg[0] = 0x90 | (channel-1);
  441.  
  442.                 (msv->msMIDImsg) ( dmsg, 3 );
  443.                 DoNote(DN_ERRORCHK);
  444.                 break;
  445.  
  446.             case DN_VELUP:
  447.  
  448.                 // adjust the velocity, then send the note ON
  449.  
  450.                 dmsg[2] += 0x10;
  451.                 if (dmsg[2] > 0x7F)
  452.                     dmsg[2] = 0x7F;
  453.  
  454.                 dmsg[1] = (channel == 10) ? patch-1 : 60;
  455.                 dmsg[0] = 0x90 | (channel-1);
  456.  
  457.                 (msv->msMIDImsg) ( dmsg, 3 );
  458.                 DoNote(DN_ERRORCHK);
  459.                 break;
  460.  
  461.             case DN_LOADPATCH:
  462.  
  463.                 dmsg[0] =  0x90;
  464.                 bend[0] =  0xE0;
  465.  
  466.                 pchg[0] = 0xc0 | (channel-1);
  467.                 pchg[1] = patch-1;
  468.  
  469.                 if ((pchg[0] & 0x0F) == 9)
  470.                     printf ("\nPercussive patch: %s\n\n",percussivenames[(patch-1)]);
  471.                 else
  472.                     printf ("\nMelodic patch: %s\n\n",melodicnames[(patch-1)]);
  473.  
  474.                 // if there is a patch library, fetch it and load it...
  475.  
  476.                 if (gdc.u.gdmi.milibrary[0])
  477.  
  478.                     VESAPreLoadPatch ( hMIDI, patch-1, channel-1 );
  479.  
  480.                 // send the program change
  481.  
  482.                 (msv->msMIDImsg)      ( pchg, 2);
  483.  
  484.                 DoNote(DN_ERRORCHK);
  485.  
  486.                 break;
  487.  
  488.             case DN_NOTEON+0x00:
  489.             case DN_NOTEON+0x01:
  490.             case DN_NOTEON+0x02:
  491.             case DN_NOTEON+0x03:
  492.             case DN_NOTEON+0x04:
  493.             case DN_NOTEON+0x05:
  494.             case DN_NOTEON+0x06:
  495.             case DN_NOTEON+0x07:
  496.             case DN_NOTEON+0x08:
  497.             case DN_NOTEON+0x09:
  498.  
  499.                 // send the note ON
  500.  
  501.                 dmsg[2] = 0x7F;
  502.                 dmsg[1] = (channel == 10) ? patch-1 : 60+(c-DN_NOTEON);
  503.                 dmsg[0] = 0x90 | (channel-1);
  504.  
  505.                 (msv->msMIDImsg) ( dmsg, 3 );
  506.                 DoNote(DN_ERRORCHK);
  507.                 break;
  508.  
  509.             case DN_NOTEOFF+0x00:
  510.             case DN_NOTEOFF+0x01:
  511.             case DN_NOTEOFF+0x02:
  512.             case DN_NOTEOFF+0x03:
  513.             case DN_NOTEOFF+0x04:
  514.             case DN_NOTEOFF+0x05:
  515.             case DN_NOTEOFF+0x06:
  516.             case DN_NOTEOFF+0x07:
  517.             case DN_NOTEOFF+0x08:
  518.             case DN_NOTEOFF+0x09:
  519.  
  520.                 // send the note OFF
  521.  
  522.                 dmsg[1] = (channel == 10) ? patch-1 : 60+(c-DN_NOTEOFF);
  523.  
  524.                 dmsg[0] = 0x80 | (channel-1);
  525.                 (msv->msMIDImsg) ( dmsg, 3 );
  526.                 DoNote(DN_ERRORCHK);
  527.  
  528.                 DoNote(DN_PITCHCNTR); // bend back to center
  529.  
  530.                 break;
  531.  
  532.             case DN_PITCHUP:
  533.  
  534.                 // pitch bend up
  535.  
  536.                 bend[0] = 0xE0 | (channel-1);
  537.  
  538.                 bend[2] += 8;
  539.                 if (bend[2] > 0x7F) bend[2] = 0x7F;
  540.  
  541.                 (msv->msMIDImsg) ( bend, 3);
  542.  
  543.                 DoNote(DN_ERRORCHK);
  544.  
  545.                 break;
  546.  
  547.             case DN_PITCHDN:
  548.  
  549.                 // pitch bend down
  550.  
  551.                 bend[0] = 0xE0 | (channel-1);
  552.  
  553.                 bend[2] -= 8;
  554.                 if (bend[2] > 0x7F) bend[2] = 0x00;
  555.  
  556.                 (msv->msMIDImsg) ( bend, 3);
  557.  
  558.                 DoNote(DN_ERRORCHK);
  559.  
  560.                 break;
  561.  
  562.             case DN_PITCHCNTR:
  563.  
  564.                 // pitch bend down
  565.  
  566.                 bend[0] = 0xE0 | (channel-1);
  567.                 bend[1] = 0x00;
  568.                 bend[2] = 0x40;
  569.  
  570.                 (msv->msMIDImsg) ( bend, 3);
  571.  
  572.                 DoNote(DN_ERRORCHK);
  573.  
  574.                 break;
  575.  
  576.             case DN_ERRORCHK:
  577.  
  578.                 len = (msv->msGetLastError) ( ); // send off the single msg
  579.                 if (len)
  580.                     printf ("The driver reported an error code of %x!\n",len);
  581.  
  582.                 break;
  583.  
  584.             default:
  585.                 break;
  586.         }
  587.  
  588.     return(c);
  589. }
  590.  
  591. ;
  592. ;   /*\
  593. ;---|*|----====< DoExit >====----
  594. ;---|*|
  595. ;---|*| Shut everything down, then exit to DOS
  596. ;---|*|
  597. ;   \*/
  598. DoExit(cc)
  599.     int cc;
  600. {
  601.  
  602.     // close the device if already opened
  603.  
  604.         if (msv)
  605.             VESACloseDevice(hMIDI);     // close the device
  606.  
  607.     // flush our callback control
  608.  
  609.         VESARegisterTimer( 255, 0, VESARateToDivisor(120) );
  610.  
  611.     // make a distinguishing mark on the screen...
  612.  
  613.         printf ("\n-------------------------------------------------\n");
  614.  
  615.     // return to DOS, don't return to caller
  616.  
  617.         exit(cc);
  618. }
  619.  
  620. ;
  621. ;   /*\
  622. ;---|*|----====< DumpHex >====----
  623. ;---|*|
  624. ;---|*| Print out, in hex, the referenced data
  625. ;---|*|
  626. ;   \*/
  627. DumpHex (pptr,len)
  628.     char far *pptr;
  629.     int len;
  630. {
  631. int n;
  632.  
  633.         for (n=0;n<len;n++) {
  634.  
  635.             if (!(n & 0x0F))
  636.                 printf ("\n%08lx:",pptr);
  637.  
  638.             printf ("%02x ",*pptr++ & 0xFF);
  639.  
  640.         }
  641. }
  642.  
  643. ;
  644. ;   /*\
  645. ;---|*|----====< GetChannel >====----
  646. ;---|*|
  647. ;---|*| Directly enter the channel number.
  648. ;---|*|
  649. ;   \*/
  650.  
  651. int GetChannel()
  652. {
  653. char str[100];
  654. int chnl;
  655.  
  656.     // do this till we ge a valid channel & key
  657.  
  658.         printf ("\n");
  659.  
  660.         chnl = channel;
  661.  
  662.         while(1) {
  663.  
  664.             // get the channel number from the user
  665.  
  666.             printf ("Enter the channel # (1-16, `?` or -1 to exit) [%d] :",chnl);
  667.             fgets  (str,99,stdin);
  668.  
  669.             if (str[0] == '?') {
  670.                 ChannelHelps();
  671.                 continue;
  672.             }
  673.             else {
  674.  
  675.                 chnl = GetValue(str,chnl);
  676.  
  677.                 if (chnl > 16) {
  678.                     chnl = channel;
  679.                     continue;
  680.                 }
  681.  
  682.                 if (chnl == -1)
  683.                     break;
  684.  
  685.                 if (chnl > 0)
  686.                     break;
  687.  
  688.             }
  689.         }
  690.  
  691.         channel = chnl;
  692.         return(-1);
  693. }
  694.  
  695. ;
  696. ;   /*\
  697. ;---|*|----====< GetNote >====----
  698. ;---|*|
  699. ;---|*| Directly enter the channel and note.
  700. ;---|*|
  701. ;   \*/
  702.  
  703. int GetNote()
  704. {
  705. char str[100];
  706. int ptch;
  707.  
  708.     // do this till we ge a valid channel & key
  709.  
  710.         printf ("\n");
  711.  
  712.     // get the patch number from the user
  713.  
  714.         ptch = patch;
  715.         str[0] = '?';
  716.  
  717.         while (str[0] == '?') {
  718.  
  719.             printf ("Enter the key # (`?` or -1 to backup) [%d] :",ptch);
  720.             fgets  (str,99,stdin);
  721.  
  722.             if (str[0] == '?')
  723.                 KeyHelps();
  724.  
  725.             ptch = GetValue(str,ptch);
  726.  
  727.             if (ptch > 128) {
  728.                 ptch = patch;
  729.                 str[0] = '?';
  730.             }
  731.         }
  732.  
  733.         // keep these values
  734.  
  735.         patch = ptch;
  736.  
  737.         return(-1);
  738. }
  739.  
  740. ;
  741. ;   /*\
  742. ;---|*|----====< GetValue >====----
  743. ;---|*|
  744. ;---|*| Return a value from the string, or the last value
  745. ;---|*|
  746. ;   \*/
  747. long GetValue (s,orig)
  748.     char * s;
  749.     long orig;
  750. {
  751. long w;
  752. int NegateFlag = FALSE;
  753.  
  754.     // if the first character is negative, then set out neg flag
  755.  
  756.         if (*s == '-') {
  757.             s++;
  758.             NegateFlag = TRUE;
  759.         }
  760.  
  761.     // check the first character, if zero, then it's octal or hex
  762.  
  763.         if (*s == '0') {
  764.  
  765.             w = 0;
  766.  
  767.             if ((*++s & 0x5F) == 'X') {
  768.  
  769.                 if (sscanf (++s,"%lx",&w) != 1)
  770.                     w = orig;
  771.  
  772.             }
  773.             else {
  774.                 if (isdigit(*s)) {
  775.  
  776.                     if (sscanf (s,"%lo",&w) != 1)
  777.                         w = orig;
  778.                 }
  779.                 else {
  780.                     w = 0;
  781.                 }
  782.             }
  783.         }
  784.  
  785.     // return a decimal value
  786.  
  787.         else {
  788.  
  789.             if (sscanf (s,"%ld",&w) != 1)
  790.                 w = orig;
  791.  
  792.         }
  793.  
  794.     // we have something...
  795.  
  796.         if (NegateFlag)
  797.             w = 0 - w;
  798.  
  799.         return(w);
  800.  
  801. }
  802.  
  803. ;
  804. ;   /*\
  805. ;---|*|----====< GiveHelps >====----
  806. ;---|*|
  807. ;---|*| Give the user the commandline option list
  808. ;---|*|
  809. ;   \*/
  810.  
  811. GiveHelps()
  812. {
  813.  
  814.         printf ("\n");
  815.         printf ("This program allows the user to enter a channel and note\n");
  816.         printf ("number to be loaded into the target MIDI device. Once the\n");
  817.         printf ("patch has been loaded, a menu of functions will be provided\n");
  818.         printf ("to allow the user to turn the note ON or OFF.\n\n");
  819.  
  820.         printf ("To Use:  DOS>note [Pxx]\n\n");
  821.         printf ("Where:   [Pxx] is the user preference #.\n\n");
  822.  
  823.         printf ("NOTE: all values are one based, so the key number ranges\n");
  824.         printf ("      from 1 to 128. Channels range from 1 to 16. Channel\n");
  825.         printf ("      number 10 is the percussive channel.\n");
  826.  
  827. }
  828.  
  829. ;
  830. ;   /*\
  831. ;---|*|----====< KeyHelps >====----
  832. ;---|*|
  833. ;---|*| Print out a list of keys
  834. ;---|*|
  835. ;   \*/
  836. KeyHelps()
  837. {
  838. int n;
  839. char str[100];
  840.  
  841.     printf ("\n");
  842.  
  843.     if (channel != 10) {
  844.  
  845.         for (n=0;n<32;n++) {
  846.             buildstr(str,n,n+32,n+64,n+96);
  847.             printf ("%s",str);
  848.         }
  849.     }
  850.     else {
  851.  
  852.         for (n=34;n<34+11;n++) {
  853.             buildstr(str,n,n+11,n+22,n+33);
  854.             printf("%s",str);
  855.         }
  856.     }
  857.  
  858.     printf ("\n");
  859.  
  860. }
  861.  
  862. ;
  863. ;   /*\
  864. ;---|*|----====< OpenTheDriver >====----
  865. ;---|*|
  866. ;---|*| Find the driver with the highest user preference, and return it to
  867. ;---|*| the caller
  868. ;---|*|
  869. ;   \*/
  870. int OpenTheDriver(pref)
  871.     int pref;
  872. {
  873. int driverpref = 256;   // real low preference
  874. long l;
  875.  
  876.     // get the device information
  877.  
  878.         do {
  879.  
  880.             // Find one MIDI device, else ]ail if non found
  881.  
  882.                 if ((hMIDI = VESAFindADevice(MIDDEVICE)) == 0)
  883.                     return(0);
  884.  
  885.             // get the device information
  886.  
  887.                 if (VESAQueryDevice(hMIDI, VESAQUERY2 ,&gdc) == 0) {
  888.                     printf ("Cannot query the installed VBE/AI devices!\n");
  889.                     DoExit(-1);
  890.                 }
  891.             // make sure ever
  892.  
  893.                 if (gdc.gdclassid != MIDDEVICE) {
  894.                     printf ("The VESA find device query returned a NON MIDI device!\n");
  895.                     DoExit(-1);
  896.                 }
  897.  
  898.             // get the drivers user preference level
  899.  
  900.                 driverpref = gdc.u.gdmi.midevpref;
  901.  
  902.             // if the caller is not expressing a preference, then use this one
  903.  
  904.                 if (pref == -1)
  905.                     break;
  906.  
  907.         } while (driverpref != pref);
  908.  
  909.     // get the memory needed by the device
  910.  
  911.         if ((memptr = AllocateBuffer(gdc.u.gdmi.mimemreq))== 0) {
  912.             printf ("We don't have memory for the device!\n");
  913.             DoExit(-1);
  914.         }
  915.  
  916.     // if the MIDI device doesn't open, bomb out...
  917.  
  918.         if ((msv = (fpMIDServ)VESAOpenADevice(hMIDI,0,memptr)) == 0) {
  919.             printf ("Cannot Open the installed devices!\n");
  920.             DoExit(-1);
  921.         }
  922.  
  923.     // if there is a patch library, load it now...
  924.  
  925.         if (gdc.u.gdmi.milibrary[0])
  926.             if (VESALoadPatchBank ( hMIDI, msv, &gdc.u.gdmi.milibrary[0] ) == 0)
  927.                 DoExit(-1);
  928.  
  929.     // callbacks, reset & other things...
  930.  
  931.         msv->msApplFreeCB = &OurFreeCBCallBack;
  932.         msv->msApplMIDIIn = &OurMIDIReceiver;
  933.         (msv->msGlobalReset)();
  934.  
  935.         return(hMIDI);
  936. }
  937.  
  938. ;
  939. ;   /*\
  940. ;---|*|----====< OurFreeCBCallBack >====----
  941. ;---|*|
  942. ;---|*| The patch block is now free. NOTE: No assumptions can be made about
  943. ;---|*| the segment registers! (DS,ES,GS,FS)
  944. ;---|*|
  945. ;   \*/
  946.  
  947. void far pascal OurFreeCBCallBack( han, patch, fptr, filler )
  948.     int  han;       // the caller's handle
  949.     int  patch;     // the actual patch #
  950.     void far *fptr; // buffer that just played
  951.     long filler;    // reserved
  952. {
  953.         // do nothing here...
  954. }
  955.  
  956.  
  957. ;
  958. ;   /*\
  959. ;---|*|----====< OurMIDIReceiver >====----
  960. ;---|*|
  961. ;---|*| Print the received data byte.
  962. ;---|*|
  963. ;   \*/
  964.  
  965. void far pascal OurMIDIReceiver ( han, delta, mbyte, filler )
  966.     int  han;       // the caller's handle
  967.     int  delta;     // the delta time
  968.     char mbyte;     // the midi byte
  969.     long filler;    // reserved
  970. {
  971. register char far *vidptr = (char far *)0xb80001E0;
  972.  
  973.     _asm {
  974.         push    ds
  975.         mov     ax,seg UserPref
  976.         mov     ds,ax
  977.     }
  978.  
  979.     *vidptr += mbyte;
  980.     *vidptr += 0x40;
  981.  
  982.     if ((int)vidptr > 0x7FF)
  983.         vidptr = (char far *)0xb80001E0;
  984.  
  985.     _asm {
  986.         pop     ds
  987.     }
  988. }
  989.  
  990. ;
  991. ;   /*\
  992. ;---|*|----====< readvalue >====----
  993. ;---|*|
  994. ;---|*| Read a value from the keyboard
  995. ;---|*|
  996. ;   \*/
  997. long readvalue()
  998. {
  999. char str[80];
  1000. int n;
  1001.  
  1002.     // get the string
  1003.  
  1004.         if (fgets (&str[0],79,stdin) == 0)
  1005.             return(0);
  1006.  
  1007.         return(GetValue(&str[0],0));
  1008. }
  1009.  
  1010. ;
  1011. ;   /*\
  1012. ;---|*|----====< sysclocktic >====----
  1013. ;---|*|
  1014. ;---|*| Return the delta of system clock ticks
  1015. ;---|*|
  1016. ;   \*/
  1017. sysclocktic()
  1018. {
  1019. int retval;
  1020. static int timer = -1;
  1021.  
  1022.     // get the clock tick, save, sub from last tick & return the value
  1023.  
  1024.         _asm {
  1025.             mov     ah,0
  1026.             int     1ah
  1027.             xchg    dx,[timer]
  1028.             sub     dx,[timer]
  1029.             mov     [retval],dx
  1030.         }
  1031.  
  1032.     // return the delta
  1033.  
  1034.         return(retval);
  1035. }
  1036.  
  1037.  
  1038.  
  1039.  
  1040.