home *** CD-ROM | disk | FTP | other *** search
/ C++ Games Programming / CPPGAMES.ISO / mt / mtsc4.c < prev    next >
C/C++ Source or Header  |  1989-01-13  |  9KB  |  279 lines

  1. /* mtsc4.c */
  2. /* `MIDI Sequencing In C', Jim Conger, M&T Books, 1989 */
  3.  
  4. /* #define TURBOC 1   Define if using TURBOC, leave out for Microsoft */
  5.  
  6. #include <stdio.h>
  7. #include <conio.h>
  8. #include <stdlib.h>
  9.  
  10. #ifdef TURBOC
  11.     #include <alloc.h>
  12. #else
  13.     #include <malloc.h>
  14. #endif
  15.  
  16. #include "standard.h"
  17. #include "screenf.h"
  18. #include "mpu401.h"
  19. #include "mt.h"
  20. #include "video.h"
  21. #include "mtsc.h"
  22. #include "mtdeclar.h"
  23.  
  24.  
  25. /* Adds note to track event list and not_time note list. Returns 1 if */
  26. /* added, 0 if aborted */
  27. void
  28. add_note(struct note_time far *first_notep, int measure, int track)
  29. {
  30.     int on_meas, on_tick, on_note, off_meas, off_tick, vel, *velp, status,
  31.         on_x, on_y, off_x, off_y;
  32.     float time_on, time_off;
  33.     struct note_time far *notetime;
  34.     struct note_pos *notepos;
  35.     struct event far *on_event;
  36.     struct event far *off_event;
  37.     
  38.     velp = &vel;
  39.     writeword("Move cross hair to NOTE START, then hit return (ESC to exit)",
  40.         1, g_graph_char_v - 1, g_norm_attrib);
  41.     notepos = select_note(measure, FALSE);
  42.     if (notepos == NULL){
  43.         clearline(g_graph_char_v - 1, g_norm_attrib);
  44.         return;
  45.     }
  46.     else{
  47.         on_meas = notepos->measure;
  48.         on_tick = notepos->tick;
  49.         on_note = notepos->note;
  50.         on_x = notepos->sprite_x;
  51.         on_y = notepos->sprite_y;
  52.         xsprite(cross, on_x, on_y, g_emph_color);   
  53.     }
  54.  
  55.     g_sc_refresh = 2;
  56.     clearline(g_graph_char_v - 1, g_norm_attrib);
  57.     writeword("Move cross hair to NOTE END, then hit return (ESC to exit)",
  58.         1, g_graph_char_v - 1, g_norm_attrib);
  59.     notepos = select_note(measure, FALSE);
  60.     if (notepos == NULL){
  61.         clearline(g_graph_char_v - 1, g_norm_attrib);
  62.         xsprite(cross, on_x, on_y, g_emph_color);
  63.         return;
  64.     }
  65.     else{
  66.         off_meas = notepos->measure;
  67.         off_tick = notepos->tick;
  68.         off_x = notepos->sprite_x;
  69.         off_y = notepos->sprite_y;
  70.         xsprite(cross, off_x, off_y, g_emph_color);
  71.     }
  72.     clearline(g_graph_char_v - 1, g_norm_attrib);
  73.     
  74.     time_on = note_to_float(on_meas, on_tick);
  75.     time_off = note_to_float(off_meas, off_tick);
  76.     if (time_off < time_on){
  77.         clearline(g_graph_char_v - 1, g_norm_attrib);
  78.         writerr("Note OFF must be after note ON - No note added.",
  79.             g_graph_char_v, g_norm_attrib, g_norm_attrib);
  80.         xsprite(cross, on_x, on_y, g_emph_color);   /* erase cross hairs */
  81.         xsprite(cross, off_x, off_y, g_emph_color);
  82.         return;
  83.     }
  84.     
  85.     status = getint(g_graph_char_v - 1, "Enter note VELOCITY (volume) (0 - 127)->",
  86.         velp, 0, 127, g_norm_attrib, g_norm_attrib);
  87.     if (!status)
  88.         vel = 64;
  89.     
  90.     advance_to_measure(track, off_meas + 1);    /* make sure measures exist */
  91.  
  92.     on_event = add_event(track, on_meas, on_tick, 4, NOTE_ON +
  93.         g_trackarray[track].midichan, on_note, vel);
  94.     off_event = add_event(track, off_meas, off_tick, 4, NOTE_ON +
  95.         g_trackarray[track].midichan, on_note, 0);
  96.     notetime = add_note_time(first_notep, on_event, on_meas, on_tick, 
  97.         off_event, off_meas, off_tick);
  98.  
  99.     xsprite(cross, on_x, on_y, g_emph_color);   /* erase cross hairs */
  100.     xsprite(cross, off_x, off_y, g_emph_color);
  101.     draw_note(notetime, g_emph_color);          /* show new note on screen */
  102.     clearline(g_graph_char_v - 1, g_norm_attrib);
  103. }
  104.  
  105.  
  106. /* add an event to track data.  Measure must exist - no check for off end */
  107. struct event far
  108. *add_event(int track, int measure, int tick, int event_bytes, int b1, int b2, 
  109.     int b3)
  110. {
  111.     int time, lastime, addtime, b0;
  112.     struct event far *ep;
  113.     struct event far *lastep;
  114.     struct event far *newep;
  115.     struct event far *nextep;
  116.     
  117.     ep = advance_to_measure(track, measure + 1);    /* make sure measure */
  118.     ep = advance_to_measure(track, measure);        /* exists, then find */
  119.     
  120.     time = 0;
  121.     while (time <= tick){   /* find event just past tick */
  122.         lastep = ep;
  123.         ep = ep->next;
  124.         b0 = ep->b[0];
  125.         if (b0 < MAX_CLOCK){        /* if a timing byte */
  126.             time += b0;
  127.             lastime = b0;
  128.         }
  129.         else if (b0 == TIME_OUT){
  130.             time += MAX_CLOCK;
  131.             lastime = MAX_CLOCK;
  132.         }               
  133.     }
  134.     time -= lastime;    /* time now equals ticks for lastep, before ep */
  135.     addtime = tick - time;
  136.     
  137.     nextep = ep;
  138.     while (nextep->b[0] == TIME_OUT){   /* go past any linked TIME_OUT's */
  139.         nextep = nextep->next;          /* nextep is first event with a */
  140.     }                                   /* timing byte, (not a TIME_OUT). */
  141.     
  142.     if (ep->b[0] != TIME_OUT){              /* normal case - just add event */
  143.         lastep->next = newep = eventalloc();
  144.         newep->next = ep;
  145.         newep->nbytes = event_bytes;
  146.         newep->b[0] = addtime;
  147.         newep->b[1] = b1;
  148.         newep->b[2] = b2;
  149.         newep->b[3] = b3;
  150.         ep->b[0] -= addtime;
  151.     }                   /* next event is time_out, convert it to new event */
  152.     else if (nextep->b[0] < addtime){
  153.         newep = ep;
  154.         ep->b[0] = addtime;
  155.         ep->b[1] = b1;
  156.         ep->b[2] = b2;
  157.         ep->b[3] = b3;
  158.         ep->nbytes = event_bytes;
  159.         nextep->b[0] += MAX_CLOCK - addtime;
  160.     }
  161.     else{           /* next event is time_out, but still need a time_out */
  162.         lastep->next = newep = eventalloc();
  163.         newep->next = ep;
  164.         newep->nbytes = event_bytes;
  165.         newep->b[0] = addtime;
  166.         newep->b[1] = b1;
  167.         newep->b[2] = b2;
  168.         newep->b[3] = b3;
  169.         nextep->b[0] -= addtime;
  170.     }
  171.     return(newep);
  172. }
  173.  
  174.  
  175. /* put a new note into the note_time linked list */
  176. struct note_time far
  177. *add_note_time(struct note_time far *first_np, struct event far *on_event,
  178.     int on_meas, int on_tick, struct event far *off_event, int off_meas, 
  179.     int off_tick)
  180. {
  181.     int first;
  182.     struct note_time far *lastnt;
  183.     struct note_time far *nextnt;
  184.     struct note_time far *newnt;
  185.     
  186.     first = 1;
  187.     lastnt = nextnt = first_np;
  188.     
  189.     while (nextnt->next != NULL && (nextnt->on_measure < on_meas || 
  190.         nextnt->on_tick <= on_tick)){
  191.         lastnt = nextnt;
  192.         nextnt = nextnt->next;
  193.         first = 0;
  194.     }
  195. #ifdef TURBOC
  196.     newnt = (struct note_time far *)farmalloc(sizeof(struct note_time));
  197. #else
  198.     newnt = (struct note_time far *)_fmalloc(sizeof(struct note_time));
  199. #endif
  200.     if (newnt == NULL){
  201.         writerr("Unable to allocate memory for note, full?", g_graph_char_v,
  202.             g_emph_attrib, g_norm_attrib);
  203.         return(NULL);
  204.     }
  205.     
  206.                     /* if newnt becomes new first note_list item */
  207.                     /* then put new data in old first item. */
  208.     if (first){
  209.         newnt->on_event = first_np->on_event;
  210.         newnt->on_measure = first_np->on_measure;
  211.         newnt->on_tick = first_np->on_tick;
  212.         newnt->note_number = first_np->on_event->b[2];
  213.         newnt->off_event = first_np->off_event;
  214.         newnt->off_measure = first_np->off_measure;
  215.         newnt->off_tick = first_np->off_tick;
  216.         newnt->next = first_np->next;
  217.                 
  218.         first_np->on_event = on_event;
  219.         first_np->on_measure = on_meas;
  220.         first_np->on_tick = on_tick;
  221.         first_np->note_number = on_event->b[2];
  222.         first_np->off_event = off_event;
  223.         first_np->off_measure = off_meas;
  224.         first_np->off_tick = off_tick;
  225.         first_np->next = newnt;
  226.         return(first_np);
  227.     }
  228.     else{
  229.         newnt->on_event = on_event;
  230.         newnt->on_measure = on_meas;
  231.         newnt->on_tick = on_tick;
  232.         newnt->note_number = on_event->b[2];
  233.         newnt->off_event = off_event;
  234.         newnt->off_measure = off_meas;
  235.         newnt->off_tick = off_tick;
  236.         lastnt->next = newnt;
  237.         newnt->next = nextnt;
  238.         return(newnt);
  239.     }
  240. }   
  241.     
  242.     
  243.  
  244. /* Allow the key velocity (volume) of a note to be changed */
  245. void
  246. change_vel(struct note_time far *first_notep, int measure)
  247. {
  248.     int vel, *velp, status;
  249.     char buf[SCRNWIDE], nbuf[10];
  250.     struct event far *ep;
  251.     struct note_pos *notepos;
  252.     struct note_time far *note_t;
  253.  
  254.     velp = &vel;
  255.     writeword("Move the cross hair to a NOTE, then hit return (ESC to exit)",
  256.         1, g_graph_char_v - 1, g_norm_attrib);
  257.     notepos = select_note(measure, FALSE);
  258.     clearline(g_graph_char_v - 1, g_norm_attrib);
  259.     if (notepos == NULL)
  260.         return;
  261.     else
  262.         note_t = find_note(first_notep, notepos->note, notepos->measure, 
  263.             notepos->tick);
  264.     
  265.     ep = note_t->on_event;
  266.     vel = ep->b[3];
  267.     itoa(vel, nbuf, 10);
  268.     strcpy(buf, "Note vel = ");
  269.     strcat(buf, nbuf);
  270.     strcat(buf, "  Enter new value (1 - 127), RET to exit.->");
  271.     status = getint(g_graph_char_v - 1, buf, velp, 0, 127, g_norm_attrib, 
  272.         g_norm_attrib);
  273.     clearline(g_graph_char_v - 1, g_norm_attrib);
  274.     if (!status)
  275.         return;
  276.     else        
  277.         ep->b[3] = vel;
  278. }
  279.