home *** CD-ROM | disk | FTP | other *** search
/ HOT Scene Stuff / hotscenestuffzyklop1996.iso / demos / sunknown / midiout.c < prev    next >
C/C++ Source or Header  |  1994-04-06  |  5KB  |  184 lines

  1. /*
  2. ** Copyright (c) 1992 Forte.  All rights reserved.
  3. ** Written late one night 6/27/93.
  4. **
  5. ** Note from Five, And Then Some:
  6. **   This file was originally included in the ultramid-package (or the
  7. **   Software Development Kit for the Gravis Ultrasound).
  8. **
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <dos.h>
  15. #include <malloc.h>
  16. #include "midi.h"
  17.  
  18. extern int not_done_playing;
  19.  
  20. /* externals */
  21. extern struct header_type header;
  22.  
  23. extern int control_break;
  24. unsigned long midi_getvarinum(struct track *track);
  25.  
  26. #pragma warn -par
  27. static void chanmessage( struct MIDILIB *ml, int c, int c1, int c2, unsigned long time)
  28. {
  29.     int chan;
  30.  
  31.     chan = c & 0x0f;
  32.     switch (c & 0xf0) {
  33.         case note_on:
  34.         (*ml->Mp_note_on)(chan, c1, c2);
  35.         break;
  36.         case note_off:
  37.         (*ml->Mp_note_off)(chan, c1, c2);
  38.         break;
  39.         case poly_aftertouch:
  40.         (*ml->Mp_pressure)(chan, c1, c2);
  41.         break;
  42.         case control_change:
  43.         (*ml->Mp_parameter)(chan, c1, c2);
  44.         break;
  45.         case pitch_wheel:
  46.         (*ml->Mp_pitch_bend)(chan, c1, c2);
  47.         break;
  48.         case program_chng:
  49.         (*ml->Mp_program)(chan, c1);
  50.         break;
  51.         case channel_aftertouch:
  52.         (*ml->Mp_chanpressure)(chan, c1, c2);
  53.         break;
  54.     }
  55. }
  56. #pragma warn .par
  57.  
  58. void midi_do_something(struct MIDILIB *ml, unsigned long now_time)
  59. {
  60.     /* This array is indexed by the high half of a status byte.  It's */
  61.     /* value is either the number of bytes needed (1 or 2) for a channel */
  62.     /* message, or 0 (meaning it's not  a channel message). */
  63.     static int chantype[] =
  64.   {
  65.         0, 0, 0, 0, 0, 0, 0, 0,        /* 0x00 through 0x70 */
  66.         2, 2, 2, 2, 1, 1, 2, 0        /* 0x80 through 0xf0 */
  67.     };
  68.     int not_done = 0,
  69.       len,
  70.       needed,
  71.       type,
  72.       i;
  73.     unsigned long us;
  74.     register struct track *track;
  75.     unsigned char c,
  76.                 c1,
  77.                 c2,
  78.                 check_next_time;
  79.  
  80.     if (now_time < ml->Mp_next_event_time)
  81.     return;
  82.  
  83.     ml->Mp_next_event_time = -1L;
  84.  
  85.     for (track=ml->Mp_tracks; track; track = track->next_track)
  86.   {
  87.       check_next_time = 1;
  88.       if (track->play_state == MPS_PLAYING)
  89.     {
  90.         while (track->play_time <= now_time)
  91.       {
  92.             check_next_time = 0;
  93.         if (*track->playp & 0x80)
  94.                 c = track->status = midi_getc(track);
  95.         else
  96.           c = track->status;
  97.             needed = chantype[ (c>>4) & 0xf ];
  98.             if (needed) /* is it a channel message? */
  99.         {
  100.           c1 = midi_getc(track);
  101.           c2 = (needed>1) ? midi_getc(track) : 0;
  102.           chanmessage( ml, c, c1, c2, now_time );
  103.             }
  104.         else
  105.         {
  106.           switch (c)
  107.           {
  108.             case MT_meta_event:
  109.               type = midi_getc(track);
  110.               len = midi_getvarinum(track);
  111.               switch (type)
  112.               {
  113.                 case MT_set_tempo:
  114.                   len -= 3;
  115.                   us = ((long)midi_getc(track)<<16) + ((long)midi_getc(track)<<8) + (long)midi_getc(track);
  116.                   for ( ; len > 0; len--)
  117.                     midi_getc(track);
  118.                   (*ml->Mp_set_tempo)(us, header.division.quarter_note);
  119.                   break;
  120.                 default:
  121.                   for (i=0; i < len; i++)
  122.                     midi_getc(track);
  123.               }
  124.                     break;
  125.                   case system_exclusive:
  126.                   case sysex_continue:
  127.                     len = midi_getvarinum(track);
  128.                     for ( i=0; i < len; i++)
  129.                         midi_getc(track);
  130.                     break;
  131.                   default: /* whoops */
  132.                     track->play_state = MPS_DONE;
  133.                     break;
  134.                 }
  135.             }
  136.             midi_get_next_time(ml, track);
  137.             if (track->play_state != MPS_PLAYING)
  138.           break;
  139.           }
  140.       }
  141.       if (track->play_state == MPS_PLAYING)
  142.     {
  143.           if (check_next_time)
  144.             if (track->play_time < ml->Mp_next_event_time)
  145.           ml->Mp_next_event_time = track->play_time;
  146.           not_done = 1;
  147.       }
  148.     }
  149.     not_done_playing = not_done;
  150. }
  151.  
  152. int midi_getc(struct track *track)
  153. {
  154.     if (track->position < track->length) {
  155.         track->position++;
  156.         return(*track->playp++);
  157.     } else {
  158.         track->play_state = MPS_DONE;
  159.         return(0);
  160.     }
  161. }
  162.  
  163. unsigned long midi_getvarinum(struct track *track)
  164. {
  165.     long value=0L;
  166.     int c;
  167.  
  168.     do {
  169.         c = midi_getc(track);
  170.         value = (value << 7) + (c & 0x7f);
  171.     } while (c & 0x80);
  172.     return (value);
  173. }
  174.  
  175. void midi_get_next_time(struct MIDILIB *ml, struct track *track)
  176. {
  177.     if (track->play_state == MPS_PLAYING) {
  178.         track->play_time += midi_getvarinum(track);
  179.         if (track->play_time < ml->Mp_next_event_time) {
  180.             ml->Mp_next_event_time = track->play_time;
  181.         }
  182.     }
  183. }
  184.