playevents.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:6k
源码类别:

多媒体编程

开发平台:

DOS

  1. /************************************************************************
  2.    playevents.c  -- actually sends sorted list of events to device
  3.    Copyright (C) 1994-1996 Nathan I. Laredo
  4.    This program is modifiable/redistributable under the terms
  5.    of the GNU General Public Licence.
  6.    You should have received a copy of the GNU General Public License
  7.    along with this program; if not, write to the Free Software
  8.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  9.    Send your comments and all your spare pocket change to
  10.    laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401
  11.    Kelly Drive, Lackland AFB, TX 78236-5128, USA.
  12.  *************************************************************************/
  13. /*    edited by Peter Kutak           */
  14. /*    email : kutak@stonline.sk       */
  15. #if defined(linux) || defined(__FreeBSD__)
  16. #include "playmidi.h"
  17. #include <sys/time.h>
  18. extern int seq_set_patch(int, int);
  19. extern void seq_key_pressure(int, int, int, int);
  20. extern void seq_start_note(int, int, int, int);
  21. extern void seq_stop_note(int, int, int, int);
  22. extern void seq_control(int, int, int, int);
  23. extern void seq_chn_pressure(int, int, int);
  24. extern void seq_bender(int, int, int, int);
  25. extern void seq_reset();
  26. SEQ_USE_EXTBUF();
  27. extern int division, ntrks, format;
  28. extern int gus_dev, ext_dev, sb_dev, awe_dev, perc, seqfd, p_remap;
  29. extern int play_gus, play_fm, play_ext, play_awe, reverb, chorus, chanmask;
  30. extern int usevol[16];
  31. extern struct miditrack seq[MAXTRKS];
  32. extern float skew;
  33. extern unsigned long int default_tempo;
  34. extern char ImPlaying,StopPlease;
  35. extern void load_sysex(int, unsigned char *, int);
  36. unsigned long int ticks, tempo;
  37. struct timeval start_time;
  38. unsigned long int rvl(s)
  39. struct miditrack *s;
  40. {
  41.     register unsigned long int value = 0;
  42.     register unsigned char c;
  43.     if (s->index < s->length && ((value = s->data[(s->index)++]) & 0x80)) {
  44. value &= 0x7f;
  45. do {
  46.     if (s->index >= s->length)
  47. c = 0;
  48.     else
  49. value = (value << 7) +
  50.     ((c = s->data[(s->index)++]) & 0x7f);
  51. } while (c & 0x80);
  52.     }
  53.     return (value);
  54. }
  55. /* indexed by high nibble of command */
  56. int cmdlen[16] =
  57. {0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0};
  58. #define CMD seq[track].running_st
  59. #define TIME seq[track].ticks
  60. #define CHN (CMD & 0xf)
  61. #define NOTE data[0]
  62. #define VEL data[1]
  63. int playevents()
  64. {
  65.     unsigned long int tempo = default_tempo, lasttime = 0;
  66.     unsigned int lowtime, track, best, length, loaded;
  67.     unsigned char *data;
  68.     double current = 0.0, dtime = 0.0;
  69.     int use_dev, play_status, playing = 1;
  70.     seq_reset();
  71.     gettimeofday(&start_time, NULL); /* for synchronization */
  72.     for (track = 0; track < ntrks; track++) {
  73. seq[track].index = seq[track].running_st = 0;
  74. seq[track].ticks = rvl(&seq[track]);
  75.     }
  76.     for (best = 0; best < 16; best++) {
  77. if (ISAWE(best))
  78.     use_dev = awe_dev;
  79. else if (ISGUS(best))
  80.     use_dev = gus_dev;
  81. else if (ISFM(best))
  82.     use_dev = sb_dev;
  83. else
  84.     use_dev = ext_dev;
  85. seq_control(use_dev, best, CTL_BANK_SELECT, 0);
  86. seq_control(use_dev, best, CTL_EXT_EFF_DEPTH, reverb);
  87. seq_control(use_dev, best, CTL_CHORUS_DEPTH, chorus);
  88. seq_control(use_dev, best, CTL_MAIN_VOLUME, 127);
  89. seq_chn_pressure(use_dev, best, 127);
  90. seq_control(use_dev, best, 0x4a, 127);
  91.     }
  92.     SEQ_START_TIMER();
  93.     SEQ_DUMPBUF();
  94.     while (playing) {
  95. lowtime = ~0;
  96. for (best = track = 0; track < ntrks; track++)
  97.     if (seq[track].ticks < lowtime) {
  98. best = track;
  99. lowtime = TIME;
  100.     }
  101. if (lowtime == ~0)
  102.     break; /* no more data to read */
  103. track = best;
  104. if (ISMIDI(CHN))
  105.     use_dev = ext_dev;
  106. else if (ISAWE(CHN))
  107.     use_dev = awe_dev;
  108. else if (ISGUS(CHN))
  109.     use_dev = gus_dev;
  110. else
  111.     use_dev = sb_dev;
  112. /* this section parses data in midi file buffer */
  113. if ((seq[track].data[seq[track].index] & 0x80) &&
  114.     (seq[track].index < seq[track].length))
  115.     CMD = seq[track].data[seq[track].index++];
  116. if (CMD == 0xff && seq[track].index < seq[track].length)
  117.     CMD = seq[track].data[seq[track].index++];
  118. if (CMD > 0xf7) /* midi real-time message (ignored) */
  119.     length = 0;
  120. else if (!(length = cmdlen[(CMD & 0xf0) >> 4]))
  121.     length = rvl(&seq[track]);
  122. if (seq[track].index + length < seq[track].length) {
  123.     /* use the parsed midi data */
  124.     data = &(seq[track].data[seq[track].index]);
  125.     if (CMD == set_tempo)
  126. tempo = ((*(data) << 16) | (data[1] << 8) | data[2]);
  127.     if (TIME > lasttime) {
  128. if (division > 0) {
  129.     dtime = ((double) ((TIME - lasttime) * (tempo / 10000)) /
  130.      (double) (division)) * skew;
  131.     current += dtime;
  132.     lasttime = TIME;
  133. } else if (division < 0)
  134.     current = ((double) TIME /
  135.        ((double) ((division & 0xff00 >> 8) *
  136.    (division & 0xff)) * 10000.0)) * skew;
  137. /* stop if there's more than 40 seconds of nothing */
  138. if (dtime > 4096.0)
  139.     playing = 0;
  140. else if ((int) current > ticks) {
  141.     SEQ_WAIT_TIME((ticks = (int) current));
  142.     SEQ_DUMPBUF();
  143. }
  144.     }
  145.     if (CMD > 0x7f && CMD < 0xf0 && ISPERC(CHN) && p_remap) {
  146. CMD &= 0xf0;
  147. CMD |= (p_remap - 1);
  148.     }
  149.     loaded = 0; /* for patch setting failures */
  150.     if (playing && CMD > 0x7f && ISPLAYING(CHN))
  151. switch (CMD & 0xf0) {
  152. case MIDI_KEY_PRESSURE:
  153.     if (ISPERC(CHN) && VEL && (!ISMIDI(CHN)&&!ISAWE(CHN)))
  154. loaded = seq_set_patch(CHN, NOTE + 128);
  155.     if (loaded != -1)
  156. seq_key_pressure(use_dev, CHN, NOTE, VEL);
  157.     break;
  158. case MIDI_NOTEON:
  159.     if (ISPERC(CHN) && VEL && (!ISMIDI(CHN)&&!ISAWE(CHN)))
  160. loaded = seq_set_patch(CHN, NOTE + 128);
  161.     if (VEL && usevol[CHN])
  162. VEL = usevol[CHN];
  163.     if (loaded != -1)
  164. seq_start_note(use_dev, CHN, NOTE, VEL);
  165.     break;
  166. case MIDI_NOTEOFF:
  167.     seq_stop_note(use_dev, CHN, NOTE, VEL);
  168.     break;
  169. case MIDI_CTL_CHANGE:
  170.     seq_control(use_dev, CHN, NOTE, VEL);
  171.     break;
  172. case MIDI_CHN_PRESSURE:
  173.     seq_chn_pressure(use_dev, CHN, NOTE);
  174.     break;
  175. case MIDI_PITCH_BEND:
  176.     seq_bender(use_dev, CHN, NOTE, VEL);
  177.     break;
  178. case MIDI_PGM_CHANGE:
  179.     if (ISMIDI(CHN) || ISAWE(CHN) || !ISPERC(CHN))
  180. NOTE = seq_set_patch(CHN, NOTE);
  181.     break;
  182. case MIDI_SYSTEM_PREFIX:
  183.     if (length > 1)
  184. load_sysex(length, data, CMD);
  185.     break;
  186. default:
  187.     break;
  188. }
  189. }
  190. /* this last little part queues up the next event time */
  191. seq[track].index += length;
  192. if (seq[track].index >= seq[track].length)
  193.     seq[track].ticks = ~0; /* mark track complete */
  194. else
  195.     seq[track].ticks += rvl(&seq[track]);
  196.     }
  197.     SEQ_DUMPBUF();
  198.     ImPlaying = 0;
  199.     return 1;
  200. }
  201. #endif /* linux || FreeBSD */