home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / musik / MIDIFP21 / SOURCES / MY_LIB / NOTIMTAB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-24  |  7.7 KB  |  251 lines

  1. /**************************************************************
  2. *
  3. *                NOTIMTAB.C
  4. *
  5. **************************************************************/
  6.  
  7. #include <acs.h>        /* because of NULL, Ax_malloc(), ... */
  8. #include <string.h>     /* because of memcmp(), ... */
  9.  
  10. #include <servimem.pif>
  11. #include <notimtab.pif>
  12.  
  13.  
  14. /********************************************************************
  15. */
  16.     int delta(
  17.         NOTE_TIME_TABLE_ELEMENT *border,     /* search till border is reached */
  18.         NOTE_TIME_TABLE_ELEMENT *position    /* search from position onwards */
  19.     )    
  20. /* Assumes "border" and "position" to be pointers
  21. * into a note_time_table. "delta" searches - starting from "position" 
  22. * in direction to "border" - for the first note in the table which ma- 
  23. * tches to the one "position" is pointing to. Two notes match - in 
  24. * the sense used here - if note number, channel and source chunk are 
  25. * equal and if the reference of the found note is still initialized.
  26. *
  27. * RETURN:  d: = 0 , if no match was found or if position == border.
  28. *             = matching position - position , else.
  29. ********************************************************************/
  30. {
  31. int d = 0;
  32. register NOTE_TIME_TABLE_ELEMENT *current ;
  33.  
  34.     current = position ;
  35.     if (border > position)
  36.     {
  37.         while ( (current < border) && !d )
  38.         {
  39.             current += 1 ;
  40.             if (!current->reference &&
  41.                  (current->note == position->note) &&
  42.                  (current->channel == position->channel) )
  43.                 d = current - position ;    
  44.         }
  45.     }
  46.     else if (border < position)
  47.     {
  48.         while ( (current > border) && !d )
  49.         {
  50.             current -= 1 ;
  51.             if (!current->reference &&
  52.                  (current->note == position->note) &&
  53.                  (current->channel == position->channel) )
  54.                 d = current - position ;    
  55.         }
  56.     }
  57.     return(d) ;
  58. }
  59.  
  60.  
  61.  
  62. /******************************************************************/
  63. /***********  PUBLISHED INTERFACE (PIF)  **************************/
  64. /******************************************************************/
  65.  
  66. unsigned int fill_note_time_table
  67. (
  68.     unsigned char *track_address,
  69.     long track_length,
  70.     NOTE_TIME_TABLE_ELEMENT *first_element,
  71.     long *elements_generated,
  72.     unsigned int *channels,
  73.     NOTE *min_note, NOTE *max_note,
  74.     char *trackname,
  75.     int max_text_length
  76. )
  77. {
  78. event *next_data = track_address, status = 0 ;
  79. NOTE_TIME_TABLE_ELEMENT *current_element = first_element;
  80. unsigned long length = 0 ; /* length of sysex or meta events */
  81. TIME time = 0, delta_time = 0 ;
  82. unsigned char read_bytes = 0 ;
  83. int d = 0,   /* reference(note on) = - reference(note off) = d */
  84.     EOT_reached = FALSE ;
  85.  
  86.     *channels = 0 ; /* up to now, all are empty */
  87.     *min_note = 0x7f ; *max_note = 0x00 ; 
  88.  
  89.     /*** while not end of track reached ***/
  90.     while (!EOT_reached)
  91.     {
  92.         /*** get next time value ***/
  93.         if ( read_var_len(next_data, &delta_time, &read_bytes) )
  94.             return no_var_length_number ;
  95.         next_data += read_bytes ; 
  96.         time += delta_time ;
  97.  
  98.         /*** get next event out of this chunk ***/
  99.         if ( (*next_data & MSN) == SYS_EX )
  100.         { 
  101.             /*** sysex or meta event or error ***/
  102.             status = 0 ;
  103.             switch (*next_data)
  104.             {
  105.             case SYS_EX: /*** sysex event transmit "f0": ignore ***/
  106.                 if ( read_var_len(next_data + 1, &length, &read_bytes) 
  107.                     == no_var_length_number ) return no_var_length_number ;
  108.                 next_data += (1 + read_bytes + length) ; break ;
  109.             case SYS_EX_NT: /*** sysex event not transmit "f0": ignore ***/
  110.                 if ( read_var_len(next_data + 1, &length, &read_bytes) 
  111.                     == no_var_length_number ) return no_var_length_number ;
  112.                 next_data += (1 + read_bytes + length) ; break ;
  113.             case META_EVENT: /*** meta event ***/
  114.                 next_data += 1 ; /* point to type of meta event */
  115.                 if ( read_var_len(next_data + 1, &length, &read_bytes) 
  116.                     == no_var_length_number ) return no_var_length_number ;
  117.                 switch (*next_data)
  118.                 {
  119.                 case END_OF_TRACK: EOT_reached = TRUE ; break ;
  120.                 case SQ_TRCK_NAME: 
  121.                     if (length >= max_text_length) {
  122.                         memcpy(trackname, next_data + 1 + read_bytes, max_text_length - 1) ;
  123.                         trackname[max_text_length - 1] = 0 ;
  124.                     }
  125.                     else {
  126.                         memcpy(trackname, next_data + 1 + read_bytes, length) ;
  127.                         trackname[length] = 0 ;
  128.                     }
  129.                 }
  130.                 next_data += (1 + read_bytes + length) ;
  131.                 break ;
  132.             default: 
  133.                 return wrong_event_found ;
  134.             }
  135.         }
  136.         else 
  137.         {
  138.             /*** midi data or channel message status byte ***/
  139.             if ( !(*next_data & STATUS) ) 
  140.             { 
  141.                 /*** data, running status must be given ***/
  142.                 if (!status) return data_without_status_given ;
  143.             }
  144.             else    
  145.             { 
  146.                 /*** channel message status byte ***/
  147.                 status = *next_data ;
  148.                 next_data += 1 ;
  149.             }
  150.             switch (status & MSN)
  151.             {
  152.             case NOTE_OFF: /* for delta: | _ON_ */ 
  153.                 current_element->note = *next_data | _ON_ ; 
  154.                 current_element->channel = status & LSN ;
  155.                 next_data += 1 ;
  156.                 current_element->dynamic = *next_data ;
  157.                 next_data += 1 ;
  158.                 current_element->time = time ;
  159.  
  160.                 /*** link note on and note off ***/
  161.                 d = delta(first_element, current_element) ; 
  162.  
  163.                 /*** reset: note off ***/
  164.                 current_element->note &= ~_ON_ ; 
  165.                 current_element->reference = d ;   
  166.                 (current_element + d)->reference = - d ;
  167.                 current_element += 1 ; 
  168.                 break ;
  169.             case NOTE_ON: 
  170.                 if (*next_data > *max_note) *max_note = *next_data ;
  171.                 if (*next_data < *min_note) *min_note = *next_data ;
  172.                 current_element->note = *next_data | _ON_ ; 
  173.                 current_element->channel = status & LSN ;
  174.                 *channels |= 0x1<<(current_element->channel) ; 
  175.                 next_data += 1 ;
  176.                 current_element->dynamic = *next_data ;
  177.                 next_data += 1 ;
  178.                 current_element->time = time ;
  179.  
  180.                 /*** note on with dynamic == 0 is note off ***/
  181.                 if (!current_element->dynamic)
  182.                 { 
  183.                     /*** link note on and note off ***/
  184.                     d = delta(first_element, current_element) ;
  185.  
  186.                     /*** switch note to off ! ***/
  187.                     current_element->note &= ~_ON_ ; 
  188.                     current_element->reference = d ;   
  189.                     (current_element + d)->reference = - d ;
  190.                     current_element += 1 ; 
  191.                 } 
  192.                 else  
  193.                 { 
  194.                     /*** normal note on:                   ***/
  195.                     /*** initialize reference and continue ***/
  196.                     current_element->reference = 0 ; 
  197.                     current_element += 1 ;
  198.                 }
  199.                 break ;
  200.             case POLY_KEY_PRESS: 
  201.             case CONTROL_CHANGE: 
  202.             case PITCH_BEND: 
  203.                 next_data += 2 ; break ; 
  204.             case PROGRAM_CHANGE: 
  205.             case CHANNEL_PRESS: 
  206.                 next_data += 1 ; break ; 
  207.             }
  208.         }
  209.         if (next_data - track_address > track_length)
  210.             return next_data_overflow ;
  211.     } 
  212. /*** <-- end while (!EOT_reached) ***/
  213.     *elements_generated = ( (long)current_element  - (long)first_element ) / 
  214.                               sizeof *first_element ;
  215. /*** return success message ***/
  216.     return note_time_table_filled ;
  217. }
  218.  
  219.  
  220.  
  221. NOTE_TIME_TABLE_ELEMENT *get_element(NOTE_TIME_TABLE_ELEMENT *first_element, 
  222.                                      unsigned long number ,
  223.                                      TIME time)
  224. {
  225. NOTE_TIME_TABLE_ELEMENT *current_element, *previous_element ;
  226. unsigned long low = 0, mid, high = number ;
  227. int found = FALSE ;
  228.  
  229.     /*** Has already the first element a higher time ? ***/
  230.     if (first_element->time >= time) return first_element ;    
  231.  
  232.     /*** Has the last element a lower time ? ***/
  233.     current_element = first_element + number - 1 ;
  234.     if (current_element->time < time) return NULL ; /* failed */
  235.  
  236.     /*** Now, number shurely is greater or equal 2 ! ***/
  237.     while (!found)
  238.         {
  239.         mid = (low + high) / 2 ;
  240.         current_element = first_element + mid ;
  241.         previous_element = current_element - 1 ;
  242.         if ((current_element->time >= time) && (previous_element->time >= time)) 
  243.              high = mid ;
  244.         else if (current_element->time < time) low = mid ;
  245.              else found = TRUE ;
  246.         if (!high) { current_element = first_element ; found = TRUE ; } ;
  247.         }
  248.     return current_element ;
  249. }
  250.