home *** CD-ROM | disk | FTP | other *** search
/ C++ Games Programming / CPPGAMES.ISO / mt / mted2.c < prev    next >
C/C++ Source or Header  |  1989-02-04  |  14KB  |  410 lines

  1. /* mted2.c   editor second module for mt */
  2. /* `MIDI Sequencing In C', Jim Conger, M&T Books, 1989 */
  3.  
  4. #include <stdio.h>  /* compiler library headers */
  5. #include <conio.h>
  6. #include <string.h>
  7.  
  8. #include "screenf.h"
  9. #include "standard.h"
  10. #include "mpu401.h"
  11. #include "mt.h"
  12. #include "video.h"
  13. #include "mtdeclar.h"
  14.  
  15. /* load the MLE screen data array (mt3[]) with current measure data */
  16. void
  17. init_meas_data(void)
  18. {
  19.     int i, j, k, status, end_track;
  20.     char nbuf[10];
  21.     struct event far *measurep;
  22.     
  23.     for (i = 0; i < NMEASURE_DISP; i++){    /* put measure #s at top */
  24.         itoa(i + 1 + g_current_measure, nbuf, 10);
  25.         strcpy(mt3[i].content, nbuf);
  26.     }
  27.     for (i = 0; i < NTRACK; i++){           /* add track names */
  28.         k = NMEASURE_DISP + (i * (NMEASURE_DISP + 2));
  29.         strcpy(mt3[k].content, g_trackarray[i].name);
  30.     }
  31.     for (i = 0; i < NTRACK; i++){           /* add midi channel numberr */
  32.         k = NMEASURE_DISP + 1 + (i * (NMEASURE_DISP + 2));
  33.         itoa(g_trackarray[i].midichan + 1, nbuf, 10);
  34.         strcpy(mt3[k].content, nbuf);
  35.     }
  36.     for (i = 0; i < NTRACK; i++){           /* see if midi data in measure */
  37.         measurep = g_trackarray[i].current;
  38.         if (measurep == g_trackarray[i].last)
  39.             end_track = 1;
  40.         else
  41.             end_track = 0;
  42.         for (j = 0; j < NMEASURE_DISP; j++){
  43.             k = j + 2 + NMEASURE_DISP + (i * (NMEASURE_DISP + 2));
  44.             if (end_track){
  45.                 strcpy(mt3[k].content, " ");
  46.             }
  47.             else{       /* put in special chars for MIDI data, empty meas.. */
  48.                 if ((status = has_midi_data(measurep)) == 2)
  49.                     strcpy(mt3[k].content, g_note_char);
  50.                 else if(status == 1)
  51.                     strcpy(mt3[k].content, g_meas_char);
  52.                 else{
  53.                     strcpy(mt3[k].content, " ");
  54.                     end_track = 1;
  55.                 }
  56.                 measurep = increment_measure(measurep);
  57.             }
  58.         }
  59.     }
  60.     if (g_block_on){                            /* put block markers in */
  61.         if (g_block_end >= g_current_measure && g_block_end <=
  62.             g_current_measure + NMEASURE_DISP){
  63.             k = NMEASURE_DISP + 2 + (g_block_track * (NMEASURE_DISP + 2)) +
  64.                 g_block_end - g_current_measure;
  65.             strcpy(mt3[k].content, g_blocke_char);
  66.         }
  67.         if (g_block_start >= g_current_measure && g_block_start <=
  68.             g_current_measure + NMEASURE_DISP){
  69.             k = NMEASURE_DISP + 2 + (g_block_track * (NMEASURE_DISP + 2)) +
  70.                 g_block_start - g_current_measure;
  71.             if (g_block_start == g_block_end)
  72.                 strcpy(mt3[k].content, g_smallb_char);
  73.             else
  74.                 strcpy(mt3[k].content, g_blocks_char);
  75.         }
  76.     }           
  77. }
  78.  
  79.  
  80. /* Checks if MIDI Note On within given measure.  Returns 0 if off end of */
  81. /* data, 1 if measure is empty, and 2 if measure has midi data. */ 
  82. int
  83. has_midi_data(struct event far *measurep)
  84. {
  85.     int first;
  86.     struct event far *eventp;
  87.     eventp = measurep;
  88.     first = 1;
  89.  
  90.     while (eventp != NULL){
  91.         if (eventp->b[1] < 0xF0 && eventp->b[3] != 0)
  92.             return(2);
  93.         else if (eventp->b[1] == MES_END)
  94.             if (!first)
  95.                 return(1);
  96.             else{
  97.                 eventp = eventp->next;
  98.                 first = 0;
  99.             }
  100.         else if (eventp->b[1] == DATA_END)
  101.             return(0);
  102.         else{
  103.             eventp = eventp->next;
  104.             first = 0;
  105.         }
  106.     }
  107.     return(0);
  108. }   
  109.     
  110.  
  111. /* find next measure end, return pointer to it.  Return NULL if off end */
  112. /* of the track's event list. */
  113. struct event far
  114. *increment_measure(struct event far *eventp)
  115. {
  116.     if (eventp == NULL || eventp->b[1] == ALL_END)
  117.         return(NULL);
  118.     else if (eventp->next != NULL){
  119.         eventp = eventp->next;
  120.         while (eventp != NULL){
  121.             if (eventp->b[1] == MES_END)
  122.                 return(eventp);
  123.             else if (eventp->b[1] == ALL_END)
  124.                 return(NULL);
  125.             else
  126.                 eventp = eventp->next;
  127.         }
  128.     }
  129.     return(NULL);
  130. }
  131.  
  132.  
  133. /* Allow cursor movement on top half of MLE screen to select a measure.  */
  134. /* Returns 0 for abort, 1 if successful. */
  135. int
  136. select_measure(struct item *item)
  137. {
  138.     int pick, track, measure;
  139.                         /* allow cursor movement - but only at screen top */
  140.     pick = movescrn(g_text_mode, mt3, NMEASURE_DISP + 2, NMEASURE_DISP + 
  141.         (NTRACK * (NMEASURE_DISP + 2)), g_emph_attrib, g_cursor_attrib);
  142.  
  143.                                         /* check if on left side or top */
  144.     if (pick < NMEASURE_DISP || ((pick - NMEASURE_DISP) % 
  145.         (NMEASURE_DISP + 2) < 2))
  146.         return(0);          /* note that ESC will return -2, quitting */
  147.     else{
  148.         track = (pick - NMEASURE_DISP)/(NMEASURE_DISP + 2);     
  149.         measure = (pick - NMEASURE_DISP - 2) - (track * (NMEASURE_DISP
  150.             + 2)) + g_current_measure;
  151.         item->track = track;
  152.         item->measure = measure;
  153.         return(1);
  154.     }
  155. }
  156.  
  157.  
  158. /* Move to given measure, add empty measures at end of track as needed */
  159. /* to extend track to measure number specified.  Returns pointer to first */
  160. /* event of that measure. */
  161. struct event far
  162. *advance_to_measure(int track, int measure)
  163. {
  164.     int m, tot_ticks, first;
  165.     struct event far *ep;
  166.     struct event far *lp;
  167.     
  168.     m = 0;
  169.     first = 1;
  170.     ep = g_trackarray[track].first;
  171.     lp = g_trackarray[track].last;
  172.     
  173.     while (ep != lp){           /* run through events counting measures */
  174.         if (ep->b[1] == MES_END){
  175.             if (!first)         /* ignore first event - always meas end */
  176.                 m++;
  177.             first = 0;
  178.         }
  179.         if (m >= measure)
  180.             return(ep);         /* found measure within existing data */
  181.         else
  182.             ep = ep->next;
  183.     }
  184.     while (m++ < measure){      /* if not, add empty measures as needed */
  185.         ep = add_measure(ep);   /* overwrites existing ALL_END event */
  186.     }
  187.     ep->next = eventalloc();    /* put end of track marker at tail */
  188.     if (ep->next == NULL)
  189.         return(NULL);
  190.     ep->next->next = NULL;
  191.     ep->next->nbytes = 2;
  192.     ep->next->b[0] = 0;
  193.     ep->next->b[1] = ALL_END;
  194.     ep->next->b[2] = ep->next->b[3] = 0;
  195.     g_trackarray[track].last = ep->next;
  196.     return(ep);                 /* returns pointer to right before ALL_END */
  197.     
  198. }
  199.  
  200.  
  201. /* Add an empty measure at starting point.  Return pointer to end event. */
  202. struct event far
  203. *add_measure(struct event far *ep)
  204. {
  205.     int tot_ticks;
  206.     
  207.     if (ep->b[1] == MES_END)            /* don't overwrite last measure end */
  208.         ep = ep->next = eventalloc();
  209.     if (ep == NULL)
  210.         return(NULL);
  211.     
  212.     tot_ticks = g_meter * g_tick;
  213.     do {
  214.         if (tot_ticks < MAX_CLOCK){     /* measure end within 240 ticks */
  215.             ep->nbytes = 2;
  216.             ep->b[0] = tot_ticks;
  217.             ep->b[1] = MES_END;
  218.             ep->b[2] = ep->b[3] = 0;
  219.         }
  220.         else{                           /* time out before measure end */
  221.             ep->nbytes = 1;
  222.             ep->b[0] = TIME_OUT;
  223.             ep->b[1] = ep->b[2] = ep->b[3] = 0;
  224.             ep = ep->next = eventalloc();
  225.             if (ep == NULL)
  226.                 return(NULL);
  227.         }
  228.         tot_ticks -= MAX_CLOCK;
  229.     } while (tot_ticks >= 0 );
  230.     return(ep);
  231. }
  232.  
  233.  
  234. /* Add the MIDI data from the measure pointed to by source_p to the data */
  235. /* in the measure pointed to by dest_p.  Correct timing bytes as needed. */
  236. struct event far
  237. *merge_measure(struct event far *dest_p, struct event far *source_p)
  238. {
  239.     int i, d_time, s_time, new_dest, new_source;
  240.     struct event far *dp_next;
  241.     struct event far *sp_next;
  242.     struct event far *newp;
  243.  
  244.     dp_next = dest_p->next;
  245.     sp_next = source_p->next;
  246.     new_dest = new_source = 1;
  247.     d_time = s_time = 0;
  248.     init_note_array();
  249.     
  250.     do {
  251.         if (new_dest){
  252.             while (dp_next->b[0] == TIME_OUT){      /* add up TIME_OUTs */
  253.                 newp = dp_next->next;
  254. #ifdef TURBOC
  255.                 farfree(dp_next);
  256. #else
  257.                 _ffree(dp_next);                    /* free their space */
  258. #endif
  259.                 dp_next = newp;
  260.                 d_time += MAX_CLOCK;
  261.             }
  262.             d_time += dp_next->b[0];
  263.             new_dest = 0;
  264.         }
  265.                                 /* keep track of notes left on or off */
  266.         fill_note_array(dp_next, dp_next->next);
  267.  
  268.         if (new_source){
  269.             while (sp_next->b[0] == TIME_OUT){
  270.                 sp_next = sp_next->next;        /* don't free from source */
  271.                 s_time += MAX_CLOCK;
  272.             }
  273.             s_time += sp_next->b[0];
  274.             new_source = 0;
  275.         }
  276.  
  277.         if (d_time <= s_time){                  /* dest event is next one */
  278.             if (d_time >= MAX_CLOCK){
  279.                 d_time -= MAX_CLOCK;            /* add TIME_OUT if needed */
  280.                 s_time -= MAX_CLOCK;
  281.                 dest_p->next = newp = eventalloc();
  282.                 if (newp == NULL)
  283.                     return(NULL);
  284.                 newp->next = dp_next;
  285.                 newp->nbytes = 1;
  286.                 newp->b[0] = TIME_OUT;
  287.                 for (i = 1; i < 4; i++){
  288.                     newp->b[i] = 0;
  289.                 }
  290.                 dest_p = newp;
  291.             }
  292.             else{
  293.                 s_time -= d_time;
  294.                 dp_next->b[0] = d_time;
  295.                 dest_p = dp_next;               /* no need to allocate - */
  296.                 dp_next = dest_p->next;         /* dest is already there */
  297.                 d_time = 0;
  298.                 new_dest = 1;
  299.             }
  300.         }
  301.         else{                                   /* source event is next */
  302.             if (s_time >= MAX_CLOCK){
  303.                 d_time -= MAX_CLOCK;            /* add TIME_OUT if needed */
  304.                 s_time -= MAX_CLOCK;
  305.                 dest_p->next = newp = eventalloc();
  306.                 if (newp == NULL)
  307.                     return(NULL);
  308.                 newp->next = dp_next;
  309.                 newp->nbytes = 1;
  310.                 newp->b[0] = TIME_OUT;
  311.                 for (i = 1; i < 4; i++){
  312.                     newp->b[i] = 0;
  313.                 }
  314.                 dest_p = newp;
  315.             }
  316.             else{                           /* add source event to dest - */
  317.                 d_time -= s_time;           /* need to alocate a new event */
  318.                 dest_p->next = newp = eventalloc();
  319.                 if (newp == NULL)
  320.                     return(NULL);
  321.                 newp->next = dp_next;
  322.                 newp->nbytes = sp_next->nbytes;
  323.                 newp->b[0] = s_time;
  324.                 for(i = 1; i < 4; i++){
  325.                     newp->b[i] = sp_next->b[i];
  326.                 }
  327.                 dest_p = newp;
  328.                 source_p = sp_next;
  329.                 sp_next = sp_next->next;
  330.                 s_time = 0;             
  331.                 new_source = 1;
  332.             }
  333.         }
  334.     } while (dest_p->b[1] != MES_END && source_p->b[1] != ALL_END);
  335.     return(dest_p);
  336. }
  337.  
  338.  
  339. /* Set all g_note_array[] values to 0 in preparation for using the array */
  340. /* to keep track of which notes have been left on after an operation. */
  341. void
  342. init_note_array(void)
  343. {
  344.     int i;
  345.     
  346.     for (i = 0; i < NNOTES; i++){
  347.         g_note_array[i] = 0;
  348.     }
  349. }
  350.  
  351.  
  352. /* Keep track of notes on/off between start_event and end_event. Notes On */
  353. /* add to the array, Notes Off subtract. */
  354. void
  355. fill_note_array(struct event far *start_event, struct event far *end_event)
  356. {
  357.     int b1, b2;
  358.     struct event far *ep;
  359.     
  360.     ep = start_event;
  361.     
  362.     while (ep != end_event){
  363.         b1 = ep->b[1];
  364.         b2 = ep->b[2];
  365.         if (b1 >= NOTE_ON && b1 < NOTE_ON + NCHANNEL){  /* if note on/off */
  366.             if (ep->b[3])               /* if a note on */
  367.                 g_note_array[b2]++;
  368.             else{                       /* if a note off */
  369.                 if (g_note_array[b2])   /* can't have negative note count */
  370.                     g_note_array[b2]--;
  371.             }
  372.         }
  373.         else if (b1 >= NOTE_OFF && b1 < NOTE_OFF + NCHANNEL){ /* note off */
  374.             if (g_note_array[b2])
  375.                 g_note_array[b2]--;
  376.         }           
  377.         ep = ep->next;
  378.     }
  379. }
  380.  
  381.  
  382. /* Add note offs at end of block, based on g_note_array[] values for */
  383. /* number of notes left on for each MIDI note number.  Returns pointer */
  384. /* to last added event. */
  385. struct event far
  386. *add_note_offs(struct event far *dest_event, int channel)
  387. {
  388.     int i, j;
  389.     struct event far *old_nextp;
  390.     
  391.     old_nextp = dest_event->next;
  392.     
  393.     for (i = 0; i < NNOTES; i++){   /* for every note in MIDI scale... */
  394.         while (g_note_array[i]--){  /* for each of this note left on ... */
  395.             dest_event = dest_event->next = eventalloc();
  396.             if (dest_event == NULL){
  397.                 dest_event->next = old_nextp;
  398.                 return(NULL);
  399.             }
  400.             dest_event->nbytes = 4; /* add a note off with same note number */
  401.             dest_event->b[0] = 0;
  402.             dest_event->b[1] = NOTE_ON + channel;
  403.             dest_event->b[2] = i;
  404.             dest_event->b[3] = 0;
  405.         }
  406.     }
  407.     dest_event->next = old_nextp;
  408.     return(dest_event);
  409. }
  410.