home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / music / patchlib / patchsrc / patch.c < prev   
Text File  |  1985-11-19  |  44KB  |  1,676 lines

  1. #include    <curses.h>
  2.  
  3. /*
  4.  *    The following source code is being placed in the public domain
  5.  *    with the sole restriction that if any of it is used in any manner,
  6.  *    proper acknowledgement will be given to the original author -
  7.  *    Eric Pettersen
  8.  */
  9.  
  10. #define    Effect        (!((Random() >> 3) % weirdness))
  11. #define sfunc(i,b)    ((types[i][b] == 1) ? "high": ((types[i][b] == 2) ? \
  12.             " mid": " low"))
  13. #define Get_roll(a)    roll = get_roll(a)
  14. #define    AND_CHAR    241
  15. #define    OPTIONS        9
  16. #define    EDIT_OPTIONS    8
  17. #define    MAIN        0
  18. #define    EDIT        1
  19. #define    OK        0
  20. #undef    NULL
  21. #define    NULL        -1
  22. #define    ABORT        -2
  23. #define    BAD        -3
  24.  
  25. #define    VOICES        1000
  26.  
  27. /* either #define DX100 or CZ101 here */
  28. #ifdef    DX100
  29. #define    RANDOM_FILE    "DX100.DTA"
  30. #define    VOICE_FILE    "DXVOICES.DTA"
  31. #define    VOICE_SIZE    77
  32. #define    TOTAL_SIZE    93
  33. #else
  34. #define    RANDOM_FILE    "CZ101.DTA"
  35. #define    VOICE_FILE    "CZVOICES.DTA"
  36. #define    VOICE_SIZE    81
  37. #define    TOTAL_SIZE    128
  38. #define    VDT        0
  39. #define    VRm        1
  40. #define    VRl        2
  41. #define VD        3
  42. #define    SLOTS        4
  43.  
  44. char    table[SLOTS][100]; /* the CZMIDI.DTA data file fits in this table */
  45. int    dca_kf[10] = { 0, 8, 17, 26, 36, 47, 58, 69, 82, 95 };
  46. int    dcw_kf[10] = { 0, 31, 44, 57, 70, 83, 96, 110, 146, 255 };
  47. #endif
  48.  
  49. int    weirdness;
  50. int    ranges[VOICE_SIZE];        /* data from DX/CZDATA.DTA    */
  51. int    types[VOICE_SIZE][2];        /* is read into these        */
  52. int    tries[VOICE_SIZE][2];        /* arrays            */
  53. char    out[80], key_tbl[384];        /* data from KEYTAB.DTA goes in */
  54.                     /* key_tbl array        */
  55. int    cur_voice, load_ptr;        /* cur_voice: points to where    */
  56.                     /* next saved voice will go in    */
  57.                     /* the voices array (and also,    */
  58.                     /* therefore, how many voices    */
  59.                     /* we have in the library)    */
  60.                     /* load_ptr: which voice from    */
  61.                     /* voices array was last loaded    */
  62.                     /* into the synth        */
  63. long    cur_space;            /* how much free space on disk    */
  64. unsigned char    voices[VOICES][TOTAL_SIZE]; /* actual voices */
  65. char    v_names[VOICES+1][80];        /* associated voice names    */
  66.  
  67. /* main: Handle all main menu I/O and call any subroutines requested */
  68. main()
  69. {
  70.     char    key, ans;
  71.     char    voice[TOTAL_SIZE], v_name[80], search_str[80];
  72.     int    i, j, name_valid, load_voice, leng, found, init_rez;
  73.  
  74.     if ((init_rez = Getrez()) == 0) Setscreen(-1L, -1L, 1);
  75.     init_curses();
  76.     scr_func(CLEAR_SCR);
  77.     printf("Getting old voices from file\n\r");
  78.     get_voices(v_names, voices);
  79.     load_ptr = -1;
  80.     printf("Getting random voice weights from file\n\r");
  81.     initialize();
  82.     show_screen(MAIN);
  83.     do {
  84.         pos_cursor(8, 3+OPTIONS);
  85.         scr_func(ERASE_TO_EOP);
  86.         switch((int)(key = Crawcin())) {
  87.         case 'n':
  88.         case 'N':
  89.             printf("n");
  90.             printf("\n\rmaking voice");
  91.             make_voice(voice);
  92.             load_ptr = cur_voice;
  93.             /* FALL THROUGH */
  94.         case 'r':
  95.         case 'R':
  96.             if (key == 'r' || key == 'R'){
  97.                 printf("r");
  98.             }
  99.             if (load_ptr < 0)
  100.                 printf("\n\rno current voice\n\r");
  101.             else {
  102.                 printf("\n\rsending voice\n\r");
  103.                 if (load_ptr == cur_voice)
  104.                     send_voice(voice);
  105.                 else 
  106.                     send_voice(voices[load_ptr]);
  107.                 show_voice(load_ptr);
  108.             }
  109.             break;
  110.         case 's':
  111.         case 'S':
  112.             printf("s");
  113.             printf("\n\rreceiving voice\n\r");
  114. #ifndef    DEBUG
  115.             receive_voice(voice);
  116. #endif
  117.             do {
  118.                 do {
  119.                     pos_cursor(0,5+OPTIONS);
  120.                     scr_func(CLEAR_TO_EOL);
  121.                     printf("enter voice name: \007");
  122.                     printf("\n\r[ESC to abort]");
  123.                     pos_cursor(18, 5+OPTIONS);
  124.                     leng = get_str(v_name);
  125.                 } while (leng == 0);
  126.                 if (leng < 0) break;
  127.                 name_valid = TRUE;
  128.                 for(i=0; i<leng; i++)
  129.                     if (v_name[i]<32 || v_name[i]>127) {
  130.                         printf("\n\rName has invalid ");
  131.                         printf("character in it - ");
  132.                         printf("re-try");
  133.                         name_valid = FALSE;
  134.                         break;
  135.                     }
  136.                 v_name[i] = '\0';
  137.                 if (name_valid)
  138.                     for(i=0; i<cur_voice; i++) {
  139.                         if(!strcmp(v_names[i],v_name))
  140.                         {
  141.                             printf("\n\rThere is al");
  142.                             printf("ready a voice");
  143.                             printf(" named '%s'",
  144.                                 v_name);
  145.                             printf(" - re-try");
  146.                             name_valid = FALSE;
  147.                             break;
  148.                         }
  149.                     }
  150.             } while(name_valid == FALSE);
  151.             if (leng < 0) break;
  152. #ifdef    DX100
  153.             strncpy(voice+77, v_name, 10); 
  154.             for(i=strlen(v_name); i<10; i++) voice[77+i] = ' ';
  155. #endif
  156.             pos_cursor(0,6+OPTIONS);
  157.             scr_func(CLEAR_TO_EOL);
  158.             for(i=0; i<TOTAL_SIZE; i++) voices[cur_voice][i] = voice[i];
  159.             strcpy(v_names[cur_voice], v_name);
  160.             printf("writing voice '%s' to file\n\r", v_name);
  161.             write_voice(v_name, voice);
  162.             cur_voice++;
  163.             show_voice(load_ptr);
  164.             break;
  165.         case 'a':
  166.         case 'A':
  167.             printf("a");
  168.             goto test;
  169.         case 'l':
  170.         case 'L':
  171.             printf("l");
  172. test:
  173.             if (cur_voice == 0) {
  174.                 warn("No voices to load");
  175.                 break;
  176.             }
  177.             if (key == 'a' || key == 'A') {
  178.                 load_ptr = (load_ptr + 1) % cur_voice;
  179.                 goto load_it;
  180.             }
  181.             load_voice = get_v_num(5+OPTIONS);
  182.             if (load_voice == ABORT) break;
  183.             load_ptr = load_voice;
  184. load_it:
  185.             pos_cursor(0,6+OPTIONS);
  186.             scr_func(CLEAR_TO_EOL);
  187.             printf("Loading voice '%s'\n\r", v_names[load_ptr]);
  188.             send_voice(voices[load_ptr]);
  189.             show_voice(load_ptr);
  190.             break;
  191.         case 'w':
  192.         case 'W':
  193.             printf("w");
  194.             do {
  195.                 pos_cursor(0, 5+OPTIONS);
  196.                 scr_func(CLEAR_TO_EOL);
  197.                 printf("New weirdness factor: ");
  198.                 leng = get_num();
  199.                 if (leng == BAD || leng == 0) {
  200.                     printf("\n\rInput 1 or higher ");
  201.                     printf("[ESC to abort]");
  202.                 }
  203.             } while(leng == 0 || leng == BAD);
  204.             if (leng > 0) {
  205.                 weirdness = leng;
  206.                 show_weirdness();
  207.             }
  208.             break;
  209.         case 'e':
  210.         case 'E':
  211.             show_screen(EDIT);
  212.             edit();
  213.             show_screen(MAIN);
  214.             break;
  215.         case 'f':
  216.         case 'F':
  217.             printf("f");
  218.             Keytbl(key_tbl, key_tbl+128, key_tbl+256); 
  219.             pos_cursor(0, 5+OPTIONS);
  220.             printf("Enter string(s) to search for: \n\r");
  221.             printf("[ESC to abort]");
  222.             pos_cursor(32, 5+OPTIONS);
  223.             leng = get_str(search_str);
  224.             Bioskeys(); 
  225.             if (leng <= 0) break;
  226.             found = -1;
  227.             pos_cursor(0, 8+OPTIONS);
  228.             printf(" #  name\n\r");
  229.             printf("--- ----");
  230.             do {
  231.                 found = search(search_str, found+1);
  232.                 if (found < cur_voice) {
  233.                     pos_cursor(0, 10+OPTIONS);
  234.                     scr_func(CLEAR_TO_EOL);
  235.                     printf("%03d '%s'", found, 
  236.                         v_names[found]);
  237.                     pos_cursor(0, 6+OPTIONS);
  238.                     scr_func(CLEAR_TO_EOL);
  239.                     printf("Continue search (y/n)? \007");
  240.                     printf("%c", (ans = Crawcin()));
  241.                 }
  242.                 else {
  243.                     pos_cursor(0, 10+OPTIONS);
  244.                     scr_func(CLEAR_TO_EOL);
  245.                     printf("*** NONE");
  246.                     pos_cursor(0, 6+OPTIONS);
  247.                     scr_func(CLEAR_TO_EOL);
  248.                     printf("-- Hit any key to continue --");
  249.                     wait();
  250.                 }
  251.             } while (found<cur_voice && (ans == 'y' || ans == 'Y'));
  252.             break;
  253.         case 'q':
  254.         case 'Q':
  255.             printf("q");
  256.             break;
  257.         default:
  258.             printf("\007");
  259.             printf("\n\rBad option '%c' - re-try", key);
  260.             break;
  261.         }
  262.     } while (key != 'q' && key != 'Q');
  263.     if (init_rez == 0) Setscreen(-1L, -1L, 0);
  264.     curses_cleanup();
  265. }
  266.  
  267. /* get_voices: read the standard voice library file and initialize the
  268.     voices in memory */
  269. get_voices(names, voice_data)
  270. char names[][80], voice_data[][TOTAL_SIZE];
  271. {
  272.     long    result;
  273.     int    handle;
  274.  
  275.     check_disk();
  276.     if (cur_space < 80 + TOTAL_SIZE) {
  277.         warn(
  278.     "WARNING: There is not enough space on the disk to store more voices");
  279.     }
  280.     result = Fsfirst(VOICE_FILE, 0);
  281.     if (result == EFILNF) {
  282.         printf("file '%s' not found -- attempting to create\n\r",
  283.             VOICE_FILE);
  284.         handle = Fcreate(VOICE_FILE, 0);
  285.         if (handle < 0) {
  286.             sprintf(out, "cannot create '%s'", VOICE_FILE);
  287.             error(out);
  288.         }
  289.         else {
  290.             printf("'%s' created\n\r", VOICE_FILE);
  291.             Fclose(handle);
  292.             result = E_OK;
  293.         }
  294.     }
  295.     if (result == E_OK) {
  296.         handle = Fopen(VOICE_FILE, READ);
  297.         if (handle < 0) {
  298.             sprintf(out, "cannot open '%s'", VOICE_FILE);
  299.             error(out);
  300.         }
  301.         else {
  302.             printf("file opened\n\r");
  303.         }
  304.     }
  305.     else {
  306.         sprintf(out, "cannot find '%s'", VOICE_FILE);
  307.         error(out);
  308.     }
  309.     cur_voice = 0;
  310.     printf("reading in voice data\n\r");
  311.     while(TRUE) {
  312.         if (scan_name(handle, names[cur_voice]) != OK) break;
  313.         if (strlen(names[cur_voice]) > 0) {
  314.             if (scan_voice(handle, voice_data[cur_voice]) != OK) 
  315.                 break;
  316.             cur_voice++;
  317.         }
  318.         else break;
  319.     }
  320.     Fclose(handle);
  321. }
  322.  
  323. /* make_voice: create a random voice and put it in 'voice' */
  324. make_voice(voice)
  325. char voice[];
  326. {
  327.     int    i, roll, wave1, wave2, nmod, rmod, line, step, sustain;
  328.     int    rate, level;    
  329.  
  330. #ifdef    DX100
  331.     for (i=0; i<VOICE_SIZE; i++) {
  332.         if (Effect) voice[i] = func(i,0);
  333.         else voice[i] = func(i,1);
  334.     }
  335.     if (!((Random() >> 3) % 4)) voice[10] = 0; /* each operator    */
  336.     if (!((Random() >> 3) % 4)) voice[23] = 0; /* (except # 1)    */
  337.     if (!((Random() >> 3) % 4)) voice[36] = 0; /* given arbitrary    */
  338.                            /* 25% chance of not */
  339.                            /* being used    */
  340.     if (!Effect) voice[11] = round(voice[11]); /* normal frequency    */
  341.     if (!Effect) voice[24] = round(voice[24]); /* ratios are     */
  342.     if (!Effect) voice[37] = round(voice[37]); /* rational multiples*/
  343.     if (!Effect) voice[50] = round(voice[50]); /* of 1.0        */
  344.     voice[49] = 99;        /* max operator 1 output */
  345.     voice[62] /= 12;
  346.     voice[62] *= 12;    /* make key change shift whole octaves */
  347.     sprintf(voice+77, "RANDOM    ");
  348.     for(i=87; i<93; i++) voice[i] = 0;
  349. #else
  350.     /* Do I want to explain how the code works for the CZ101? NOOO!!! *
  351.      * I suggest you get a copy of CZ101 MIDI system exclusive specs  *
  352.      * and then examine the code closely.  What makes this stuff so   *
  353.      * hard to understand is that the random values have to be put    *
  354.      * into specific *bit positions* in specific bytes, instead of    *
  355.      * being given bytes of their very own, i.e. several different    *
  356.      * values are stuffed into a specific byte.  If there is something*
  357.      * crucial that you cannot understand you can E-mail me.  If you  *
  358.      * scrap the code and write your own, I suggest you retain CZMIDI.*
  359.      * DTA because that is a pain to generate by hand.          */
  360.     Get_roll(0);
  361.     roll = (roll - 1) % 3;
  362.     voice[0] = 0 | (roll << 2) | (line = 3); 
  363.         /* Line select and Octave */
  364.     voice[1] = (Random() >> 3) % 2; 
  365.         /* Detune + or - */
  366.     Get_roll(1);
  367.     voice[2] = (((10*roll)/151) << 4) + ((roll + roll/15 - 1) % 16);
  368.         /* Fine Detune */
  369.     Get_roll(2);
  370.     voice[3] = roll;
  371.         /* Octave and Note Detune */
  372.     Get_roll(3);
  373.     voice[4] = 8/(roll+1) + (roll == 3) * 28;
  374.         /* Vibrato Waveform */
  375.     Get_roll(4);
  376.     voice[5] = roll;
  377.     voice[6] = table[VDT][roll];
  378.     voice[7] = (roll > 79) + (roll > 95);
  379.         /* Vibrato Delay Time (3 bytes) */
  380.     Get_roll(5);
  381.     voice[8] = roll;
  382.     voice[9] = table[VRl][roll];
  383.     voice[10] = table[VRm][roll];
  384.         /* Vibrato Rate (3 bytes) */
  385.     Get_roll(6);
  386.     voice[11] = roll;
  387.     voice[12] = table[VD][roll];
  388.     voice[13] = (roll > 78) + (roll > 94) + (roll > 98);
  389.         /* Vibrato Depth (3 bytes) */
  390.     for(i=0; i<2; i++) {
  391.         Get_roll(7+i*37);
  392.         wave1 = roll;
  393.         Get_roll(8+i*37);
  394.         if (roll) {
  395.             Get_roll(9+i*37);
  396.             wave2 = roll+1;
  397.             if (wave1 > 4 && wave2 > 5) wave2 = 0;
  398.         }
  399.         else wave2 = 0;
  400.         Get_roll(10+i*37);
  401.         if (!(rmod = roll)) {
  402.             Get_roll(11+i*37);
  403.             nmod = roll;
  404.         } else nmod = 0;
  405.         if (i || line < 2) nmod = rmod = 0;
  406.         voice[14+i*57] = 
  407.             ((wave1 < 3 ? wave1 : (wave1 > 4 ? 6 : wave1+1)) << 5)
  408.             +(wave2>0)*((wave2<4 ? wave2-1:(wave2>5 ? 6:wave2))<<2)
  409.             +((wave2 > 0) << 1);
  410.             /* DCO waves */
  411.         wave2--;
  412.         voice[15+i*57] = 
  413.             ((max(wave1,wave2) > 4 ? max(wave1,wave2)-4 : 0) << 6)
  414.             + (rmod << 5) + ((3*nmod) << 3);
  415.             /* Modulation and DCO wave resonance */
  416.         Get_roll(12+i*37);
  417.         voice[16+i*57] = roll;
  418.         voice[17+i*57] = dca_kf[roll];
  419.             /* DCA Key Follow */
  420.         Get_roll(13+i*37);
  421.         voice[18+i*57] = roll;
  422.         voice[19+i*57] = dcw_kf[roll];
  423.             /* DCW Key Follow */
  424.         Get_roll(14+i*37);
  425.         if (!i && roll < 1) roll = 1;
  426.         voice[20+i*57] = roll;
  427.             /* DCA End Step */
  428.         if (Effect) sustain = 8;
  429.         else sustain = mid(voice[20+i*57], 3);
  430.         if (sustain == voice[20+i*57]) sustain = 8;
  431.         Get_roll(15+i*37);
  432.         rate = roll;
  433.         voice[21+i*57] = (119 * rate) / 99;
  434.             /* DCA Attack Rate */
  435.         Get_roll(16+i*37);
  436.         level = roll;
  437.         voice[22+i*57] = (sustain == 0 ? 128 : 0) +
  438.             (level == 0 ? 0 : level+28);
  439.             /* DCA Attack Level */
  440.         for (step=1; step<voice[20+i*57]; step++) {
  441.             if (sustain < 8) {
  442.                 if (step < sustain) {
  443.                     Get_roll(17+i*37);
  444.                     rate = roll;
  445.                     Get_roll(18+i*37);
  446.                     level = roll;
  447.                 }
  448.                 else if (step == sustain) {
  449.                     Get_roll(19+i*37);
  450.                     rate = roll;
  451.                     Get_roll(20+i*37);
  452.                     level = roll;
  453.                 }
  454.                 else {
  455.                     Get_roll(21+i*37);
  456.                     rate = roll;
  457.                     Get_roll(22+i*37);
  458.                     level = roll;
  459.                 }
  460.             }
  461.             else if (step < (voice[20+i*37]+1)/2) {
  462.                 Get_roll(17+i*37);
  463.                 rate = roll;
  464.                 Get_roll(18+i*37);
  465.                 level = roll;
  466.             }
  467.             else {
  468.                 Get_roll(21+i*37);
  469.                 rate = roll;
  470.                 Get_roll(22+i*37);
  471.                 level = roll;
  472.             }
  473.             voice[21+2*step+i*57] = (level < (voice[20+2*step+i*57]
  474.                 & 0x007F) ? 128 : 0) + ((119 * rate)/99);
  475.                 /* DCA intermediate rate */
  476.             voice[22+2*step+i*57] = (sustain == step ? 128 : 0) +
  477.                 (level == 0 ? 0 : level+28);
  478.                 /* DCA intermediate level */
  479.         }
  480.         Get_roll(23+i*37);
  481.         rate = roll;
  482.         voice[21+2*step+i*57] = 128 + ((119 * rate)/99);
  483.             /* DCA End Rate */
  484.         voice[22+2*step+i*57] = 0;
  485.             /* DCA End Level */
  486.         for(step=step+1;step<8;step++) {
  487.             voice[21+2*step+i*57] = (119*50)/99;
  488.             voice[22+2*step+i*57] = 0;
  489.             /* Envelope cleanup */
  490.         }
  491.         Get_roll(24+i*37);
  492.         voice[37+i*57] = roll;
  493.             /* DCW End Step */
  494.         if (Effect) sustain = 8;
  495.         else sustain = mid(voice[37+i*57], 3);
  496.         if (sustain == voice[37+i*57]) sustain = 8;
  497.         Get_roll(25+i*37);
  498.         rate = roll;
  499.         Get_roll(26+i*37);
  500.         level = roll;
  501.         voice[38+i*57] = (119 * rate) / 99;
  502.             /* DCW Attack Rate */
  503.         voice[39+i*57] = (127 * level) / 99;
  504.             /* DCW Attack Level */
  505.         for (step=1; step<voice[37+i*57]; step++) {
  506.             if (sustain < 8) {
  507.                 if (step < sustain) {
  508.                     Get_roll(27+i*37);
  509.                     rate = roll;
  510.                     Get_roll(28+i*37);
  511.                     level = roll;
  512.                 }
  513.                 else if (step == sustain) {
  514.                     Get_roll(29+i*37);
  515.                     rate = roll;
  516.                     Get_roll(30+i*37);
  517.                     level = roll;
  518.                 }
  519.                 else {
  520.                     Get_roll(31+i*37);
  521.                     rate = roll;
  522.                     Get_roll(32+i*37);
  523.                     level = roll;
  524.                 }
  525.             }
  526.             else if (step < (voice[20+i*37]+1)/2) {
  527.                 Get_roll(27+i*37);
  528.                 rate = roll;
  529.                 Get_roll(28+i*37);
  530.                 level = roll;
  531.             }
  532.             else {
  533.                 Get_roll(31+i*37);
  534.                 rate = roll;
  535.                 Get_roll(32+i*37);
  536.                 level = roll;
  537.             }
  538.             voice[38+2*step+i*57] = (level < (voice[37+2*step+i*57]
  539.                 & 0x007F) ? 128 : 0) + ((119 * rate)/99);
  540.                 /* DCW intermediate rate */
  541.             voice[39+2*step+i*57] = (sustain == step ? 128 : 0) +
  542.                 ((127 * level) / 99);
  543.                 /* DCW intermediate level */
  544.         }
  545.         Get_roll(33+i*37);
  546.         rate = roll;
  547.         voice[38+2*step+i*57] = 128 + ((119 * rate)/99);
  548.             /* DCW End Rate */
  549.         voice[39+2*step+i*57] = 0;
  550.             /* DCW End Level */
  551.         for(step=step+1;step<8;step++) {
  552.             voice[38+2*step+i*57] = (119*50)/99;
  553.             voice[39+2*step+i*57] = 0;
  554.             /* Envelope cleanup */
  555.         }
  556.         Get_roll(34+i*37);
  557.         voice[54+i*57] = roll;
  558.             /* DCO End Step */
  559.         if (Effect) sustain = 8;
  560.         else sustain = mid(voice[54+i*57], 3);
  561.         if (sustain == voice[54+i*57]) sustain = 8;
  562.         Get_roll(35+i*37);
  563.         rate = roll;
  564.         Get_roll(36+i*37);
  565.         level = roll;
  566.         voice[55+i*57] = (127 * rate) / 99;
  567.             /* DCO Attack Rate */
  568.         voice[56+i*57] = (level < 64 ? level : level+4);
  569.             /* DCO Attack Level */
  570.         for (step=1; step<voice[54+i*57]; step++) {
  571.             if (sustain < 8) {
  572.                 if (step < sustain) {
  573.                     Get_roll(37+i*37);
  574.                     rate = roll;
  575.                     Get_roll(38+i*37);
  576.                     level = roll;
  577.                 }
  578.                 else if (step == sustain) {
  579.                     Get_roll(39+i*37);
  580.                     rate = roll;
  581.                     Get_roll(40+i*37);
  582.                     level = roll;
  583.                 }
  584.                 else {
  585.                     Get_roll(41+i*37);
  586.                     rate = roll;
  587.                     Get_roll(42+i*37);
  588.                     level = roll;
  589.                 }
  590.             }
  591.             else if (step < (voice[20+i*37]+1)/2) {
  592.                 Get_roll(37+i*37);
  593.                 rate = roll;
  594.                 Get_roll(38+i*37);
  595.                 level = roll;
  596.             }
  597.             else {
  598.                 Get_roll(41+i*37);
  599.                 rate = roll;
  600.                 Get_roll(42+i*37);
  601.                 level = roll;
  602.             }
  603.             voice[55+2*step+i*57] = (level < (voice[54+2*step+i*57]
  604.                 & 0x007F) ? 128 : 0) + ((127 * rate)/99);
  605.                 /* DCO intermediate rate */
  606.             voice[56+2*step+i*57] = (sustain == step ? 128 : 0) +
  607.                 (level < 64 ? level : level+4);
  608.                 /* DCO intermediate level */
  609.         }
  610.         Get_roll(43+i*37);
  611.         rate = roll;
  612.         voice[55+2*step+i*57] = 128 + ((127 * rate)/99);
  613.             /* DCO End Rate */
  614.         voice[56+2*step+i*57] = 0;
  615.             /* DCO End Level */
  616.         for(step=step+1;step<8;step++) {
  617.             voice[55+2*step+i*57] = (127*50)/99;
  618.             voice[56+2*step+i*57] = 0;
  619.             /* Envelope cleanup */
  620.         }
  621.     }
  622.     for (i=0; i<TOTAL_SIZE; i++)
  623.         voice[i] = (voice[i] << 4) + (0x000F & (voice[i] >> 4));
  624.         /* Casio sends nibbles in *reverse* order */
  625. #endif
  626. }
  627.  
  628. /* send_voice: send a voice ('voice') to the synth */
  629. send_voice(voice)
  630. char voice[];
  631. {
  632.     int    i,j;
  633.     char    checksum;
  634.  
  635. #ifdef    CZ101
  636. retry:
  637.     midi_flush();
  638. #endif
  639.     send('\360');
  640. #ifdef    DX100
  641.     send('\103');
  642.     send('\000');
  643.     send('\003');
  644.     send('\000');
  645.     send('\135');
  646.     checksum = 0;
  647.     for(i=0;i<TOTAL_SIZE;i++) {
  648.         send(voice[i]);
  649.         checksum += ~voice[i] + 1;
  650.     }
  651.     checksum &= '\177';
  652.     send(checksum);
  653. #else
  654.     send('\104');
  655.     send('\000');
  656.     send('\000');
  657.     send('\160');
  658.     send('\040');
  659.     send('\140');
  660.     if(!handshake('\360')) goto retry;
  661.     if(!handshake('\104')) goto retry;
  662.     if(!handshake('\000')) goto retry;
  663.     if(!handshake('\000')) goto retry;
  664.     if(!handshake('\160')) goto retry;
  665.     if(!handshake('\060')) goto retry;
  666.     for(i=0; i<TOTAL_SIZE; i++) {
  667.         send((char)(0x000F & (voice[i] >> 4)));
  668.         send((char)(0x000F & voice[i]));
  669.     }
  670.     for (i=0; i<256 - 2*TOTAL_SIZE; i++) send('\000');
  671. #endif
  672.     send('\367');
  673. #ifdef    CZ101
  674.     if(!handshake('\367')) goto retry;
  675. #endif
  676. }
  677.  
  678. /* receive_voice: receive a voice from the synth and place it in 'voice' */
  679. receive_voice(voice)
  680. char voice[];
  681. {
  682.     int    i,j;
  683. #ifdef    DX100
  684.     char    checksum, test;
  685. #else
  686.     char    high, low;
  687. #endif
  688.  
  689. retry:
  690.     midi_flush();
  691.     send('\360');
  692. #ifdef    DX100
  693.     send('\103');
  694.     send('\040');
  695.     send('\003');
  696.     send('\367');
  697.     for(i=0;i<5;i++) {
  698.         while((test=Bconin(3)) & '\200');
  699.     }
  700.     test = 0;
  701.     for(i=0;i<TOTAL_SIZE;i++) {
  702.         while((voice[i] = Bconin(3)) & '\200');
  703.         test += ~voice[i] + 1;
  704.     }
  705.     test &= '\177';
  706.     while((checksum = Bconin(3)) & '\200');
  707.     if (test == checksum) { 
  708.         printf("good checksum\n\r");
  709.     }
  710.     else {
  711.         printf("bad checksum -- re-trying\n\r");
  712.         goto retry;
  713.     }
  714. #else
  715.     send('\104');
  716.     send('\000');
  717.     send('\000');
  718.     send('\160');
  719.     send('\020');
  720.     send('\140');
  721.     if (!handshake('\360')) goto retry;
  722.     if (!handshake('\104')) goto retry;
  723.     if (!handshake('\000')) goto retry;
  724.     if (!handshake('\000')) goto retry;
  725.     if (!handshake('\160')) goto retry;
  726.     if (!handshake('\060')) goto retry;
  727.     send('\160');
  728.     send('\061');
  729.     for(i=0;i<TOTAL_SIZE;i++) { 
  730.         while((high = Bconin(3)) & '\200');
  731.         while((low = Bconin(3)) & '\200');
  732.         voice[i] = (high << 4) + low;
  733.     }
  734.     send('\367');
  735. #endif    
  736. }
  737.  
  738. /* write_voice: write voice 'voice' with name 'name' to the standard
  739.     library file */
  740. write_voice(name, voice)
  741. char name[], voice[];
  742. {
  743.     int    handle;
  744.     
  745.     if (cur_voice >= VOICES) {
  746.         printf("At voice number limit [%d], to save current voice:\n\r",
  747.             VOICES);
  748.         printf("   (1) use 'quit' option to exit program.\n\r");
  749.         printf("   (2) rename file %s to any other name.\n\r", 
  750.             VOICE_FILE);
  751.         printf("   (3) restart program and save voice.\n\r");
  752.         printf("Note: To access the voices stored in the old ");
  753.         printf("%s it must be renamed back\n\rto %s ", VOICE_FILE,
  754.             VOICE_FILE);
  755.         printf("and the current %s named something else ", VOICE_FILE);
  756.         printf("temporarily.\n\r");
  757.         printf("-- hit any key to continue --");
  758.         wait();
  759.         return;
  760.     }
  761.     if (cur_space < 94 + strlen(name))
  762.         error("Not enough free space on disk to store voice data");
  763.     handle = Fopen(VOICE_FILE, READ_WRITE);
  764.     if (handle < 0) {
  765.         sprintf(out, "Cannot open '%s'", VOICE_FILE);
  766.         error(out);
  767.     }
  768.     Fseek(0L, handle, 2);
  769.     if (Fwrite(handle, (long)(strlen(name) + 1), name) < 0)
  770.         error("Error while writing voice name to file");
  771.     cur_space -= strlen(name)+1;
  772.     if (Fwrite(handle, (long)TOTAL_SIZE, voice) < 0)
  773.         error("Error while writing voice data to file");
  774.     cur_space -= TOTAL_SIZE;
  775.     Fclose(handle);
  776.     if (cur_space < 80 + TOTAL_SIZE) {
  777.         warn(
  778. "WARNING: there may not be enough space on the current disk for another voice");
  779.     }
  780.     if (cur_voice == VOICES-1) {
  781.         printf("WARNING: voice number limit of %d reached\n\r", VOICES);
  782.         printf("To save more voices:\n\r");
  783.         printf("   (1) use 'quit' option to exit program.\n\r");
  784.         printf("   (2) rename file %s to any other name.\n\r",
  785.             VOICE_FILE);
  786.         printf("   (3) restart program.\n\r");
  787.         printf("Note: To access the voices stored in the old ");
  788.         printf("%s it must be renamed back\n\rto %s ", VOICE_FILE,
  789.             VOICE_FILE);
  790.         printf("and the current %s named something else ", VOICE_FILE);
  791.         printf("temporarily.\n\r");
  792.         printf("-- hit any key to continue --");
  793.         wait();
  794.     }
  795. }
  796.  
  797. /* scan_name: read a voice name from a file with handle 'handle' into 'name',
  798.     returning the success of the operation */
  799. int
  800. scan_name(handle, name)
  801. int    handle;
  802. char    name[];
  803. {
  804.     if (Fread(handle, 1L, name) == 0) {
  805.         name[0] = '\0';
  806.     }
  807.     else do {
  808.         name++;
  809.         if (Fread(handle, 1L, name) == 0) {
  810.         warn("unexpected end-of-file in voice file -- check voices");
  811.             return(BAD);
  812.         }
  813.     } while(*name != '\0');
  814.     return(OK);
  815. }
  816.  
  817. /* scan_voice: read a voice from a file with handle 'handle' into 'voice',
  818.     returning the success of the operation */
  819. int
  820. scan_voice(handle, voice)
  821. int    handle;
  822. char    voice[];
  823. {
  824.     if (Fread(handle, (long)TOTAL_SIZE, voice) != TOTAL_SIZE) {
  825.         warn("Unexpected end-of-file in voice file -- check voices");
  826.         return(BAD);
  827.     }
  828.     return(OK);
  829. }
  830.  
  831. /* error: print message 'message', wait, and terminate */
  832. error(message)
  833. char *message;
  834. {
  835.     scr_func(CLEAR_SCR);
  836.     printf("%s\n\r", message);
  837.     printf("\n\r-- hit any key to exit --\n\r");
  838.     wait();
  839.     curses_cleanup();
  840.     exit();
  841. }
  842.  
  843. /* warn: print message 'message', wait, and continue */
  844. warn(message)
  845. char    *message;
  846. {
  847.     printf("\n\r%s\n\r", message);
  848.     printf("-- hit any key to continue --\n\r");
  849.     wait();
  850. }
  851.  
  852. /* midi_flush: flush the MIDI input buffer */
  853. midi_flush()
  854. {
  855.     while(Bconstat(3)) Bconin(3);
  856. }
  857.  
  858. /* send: send the byte 'data' to MIDI out */
  859. send(data)
  860. char    data;
  861. {
  862.     while(!Bcostat(3));
  863.     Bconout(3, data);
  864. }
  865.  
  866. /* mid: find the median of 'rolls' numbers between zero and 'range' */
  867. mid(range, rolls)
  868. int    range, rolls;
  869. {
  870.     int    i, lowest, place, j;
  871.     int    results[100];
  872.  
  873.     for(i=0; i<rolls; i++)
  874.         results[i] = Random() % (range+1);
  875.     for(i=0; i<rolls/2; i++) {
  876.         lowest = range;
  877.         for(j=0;j<rolls;j++)
  878.             if(results[j] < lowest) {
  879.                 lowest = results[j];
  880.                 place = j;
  881.             }
  882.         results[place] = range;
  883.     }
  884.     lowest = range;
  885.     for(j=0;j<rolls;j++)
  886.         if(results[j] < lowest) {
  887.             lowest = results[j];
  888.             place = j;
  889.         }
  890.     return(lowest);
  891. }
  892.  
  893. /* low: find the lowest of 'rolls' numbers in the range zero to 'range' */
  894. low(range, rolls)
  895. int    range, rolls;
  896. {
  897.     int    i, lowest, roll;
  898.  
  899.     lowest = range;
  900.     for(i=0; i<rolls; i++) 
  901.         if ((roll = Random() % (range+1)) < lowest) lowest = roll;
  902.     return(lowest);
  903. }
  904.  
  905. /* high: find the highest of 'rolls' numbers in the range zero to 'range' */
  906. high(range, rolls)
  907. int    range, rolls;
  908. {
  909.     int    i, highest, roll;
  910.  
  911.     highest = 0;
  912.     for(i=0; i<rolls; i++) 
  913.         if ((roll = Random() % (range+1)) > highest) highest = roll;
  914.     return(highest);
  915. }
  916.  
  917. /* initialize: initialize various tables and variables */
  918. initialize()
  919. {
  920.     int    i, handle, slot;
  921.  
  922.     if ((handle = Fopen("KEYTAB.DTA", READ)) < 0)
  923.         error("Cannot open 'KEYTAB.DTA'");
  924.     if (Fread(handle, 384L, key_tbl) < 384)
  925.         error("Read error on 'KEYTAB.DTA'");
  926.     Fclose(handle);
  927.     handle = Fopen(RANDOM_FILE, READ);
  928.     if (handle < 0)
  929.         error("Cannot open random weight file");
  930.     weirdness = 50;
  931.     for (i=0; i<VOICE_SIZE; i++) ranges[i] = get_int(handle);
  932.     for (i=0; i<VOICE_SIZE; i++) {
  933.         types[i][0] = get_int(handle);
  934.         types[i][1] = get_int(handle);
  935.     }
  936.     for (i=0; i<VOICE_SIZE; i++) {
  937.         tries[i][0] = get_int(handle);
  938.         tries[i][1] = get_int(handle);
  939.     }
  940.     Fclose(handle);
  941. #ifdef    CZ101
  942.     handle = Fopen("CZMIDI.DTA", READ);
  943.     if (handle < 0) error("Cannot open MIDI table file");
  944.     for (slot=0; slot<SLOTS; slot++) for(i=0; i<100; i++) {
  945.         if (Fread(handle, 1L, &table[slot][i]) < 1)
  946.             error("Unexpected EOF in 'CZMIDI.DTA'");
  947.     }
  948.     Fclose(handle);
  949. #endif
  950. }
  951.  
  952. /* get_int: read an integer from the file pointed to by 'handle',
  953.     ignoring non-numeric characters */
  954. int
  955. get_int(handle)
  956. int    handle;
  957. {
  958.     char    data;
  959.     int    num, in_comment;
  960.  
  961.     in_comment = FALSE;
  962.     do {
  963.         if (Fread(handle, 1L, &data) < 1) {
  964.             sprintf(out, "Unexpected EOF in '%s'", RANDOM_FILE);
  965.             error(out);
  966.         }
  967.         if (data == '*') in_comment = !in_comment;
  968.     } while(data < '0' || data > '9' || in_comment);
  969.     num = data - '0';
  970.     if (Fread(handle, 1L, &data) < 1) {
  971.         sprintf(out, "Unexpected EOF in '%s'", RANDOM_FILE);
  972.         error(out);
  973.     }
  974.     else if (data >= '0' && data <= '9')
  975.         num = 10*num + data - '0';
  976.     return(num);
  977. }
  978.  
  979. /* get_num: read an integer from the keyboard and return it or an error code */
  980. int    
  981. get_num()
  982. {
  983.     int    i, num, leng;
  984.  
  985.     if ((leng = get_str(out)) < 0) return(ABORT);
  986.     else if (leng == 0) return(NULL);
  987.     num = 0;
  988.     for(i=0; i<leng; i++) {
  989.         if (out[i] < '0' || out[i] > '9')
  990.             return(BAD);
  991.         else
  992.             num = 10*num + out[i] - '0';
  993.     }
  994.     return(num);
  995. }
  996.  
  997. /* handshake: wait for character 'verify' from the CZ101 */
  998. handshake(verify)
  999. char    verify;
  1000. {
  1001.     int    received;
  1002.  
  1003.     while(!Bconstat(3));
  1004.     if ((received = (0x00FF & Bconin(3))) != (0x00FF & verify)) {
  1005.         warn("Bad handshaking from synth - Make sure MIDI channel = 1");
  1006.         sprintf(out, "Expecting %x but received %x", (int) verify,
  1007.             received);
  1008.         warn(out);
  1009.         sprintf(out, "Next byte = %x", (0x00FF & Bconin(3)));
  1010.         error(out);
  1011.         return(FALSE);
  1012.     }
  1013.     return(TRUE);
  1014. }
  1015.  
  1016. /* show_weirdness: display the weirdness factor on the screen */
  1017. show_weirdness()
  1018. {
  1019.     pos_cursor(40, 2);
  1020.     scr_func(CLEAR_TO_EOL);
  1021.     sprintf(out, "weirdness factor = 1 in %d", weirdness);
  1022.     pos_cursor(80 - strlen(out), 2);
  1023.     printf("%s", out);
  1024. }
  1025.  
  1026. /* show_voice: show the name and voice number of voice number 'voice'
  1027.     on the screen */
  1028. show_voice(voice)
  1029. {
  1030.     pos_cursor(77, 3);
  1031.     if (voice < 0) printf("---");
  1032.     else printf("%03d", voice);
  1033.     pos_cursor(40, 4);
  1034.     scr_func(CLEAR_TO_EOL);
  1035.     if (voice < 0) {
  1036.         pos_cursor(76, 4);
  1037.         printf("NONE");
  1038.     }
  1039.     else if (voice == cur_voice) {
  1040.         pos_cursor(74, 4);
  1041.         printf("RANDOM");
  1042.     }
  1043.     else {
  1044.         pos_cursor(max(78-strlen(v_names[voice]),40), 4);
  1045.         printf("'%s'", v_names[voice]);
  1046.     }
  1047. }
  1048.  
  1049. /* show_screen: if 'screen' equals MAIN, display the main menu,
  1050.     otherwise display the edit menu */
  1051. show_screen(screen)
  1052. int    screen;
  1053. {
  1054.     scr_func(CLEAR_SCR);
  1055.     if (screen == MAIN) {
  1056.         printf("OPTIONS\n\r");
  1057.         printf("-------\n\r");
  1058.         printf("n = generate and load new voice\n\r");
  1059.         printf("s = save currently loaded [and edited] voice\n\r");
  1060.         printf("r = reload current voice\n\r");
  1061.         printf("l = load previously saved voice\n\r");
  1062.         printf("a = audition next voice in library\n\r");
  1063.         printf("w = change weirdness factor\n\r");
  1064.         printf("e = edit voice library\n\r");
  1065.         printf("f = find voice by name\n\r");
  1066.         printf("q = quit\n\r");
  1067.         printf("\n\rOption? ");
  1068.         show_weirdness();
  1069.         sprintf(out, "current voice #   ");
  1070.         pos_cursor(80 - strlen(out), 3);
  1071.         printf("%s", out);
  1072.         show_voice(load_ptr);
  1073.     }
  1074.     else {
  1075.         printf("EDIT OPTIONS\n\r");
  1076.         printf("---- -------\n\r");
  1077.         printf("c = change voice name\n\r");
  1078.         printf("d = delete voice\n\r");
  1079.         printf("D = delete range of voices\n\r");
  1080.         printf("m = move voice\n\r");
  1081.         printf("M = move range of voices\n\r");
  1082.         printf("r = read in and append voices from alternate file\n\r");
  1083.         printf("x = execute changes and return to main menu\n\r");
  1084.         printf("q = quit edit menu, abandoning changes\n\r");
  1085.         printf("\n\rOption? ");
  1086.     }
  1087. }
  1088.  
  1089. /* list_voices: list the voice names and numbers available in the library */
  1090. list_voices()
  1091. {
  1092.     int    i,j;
  1093.  
  1094.     pos_cursor(0,14);
  1095.     scr_func(ERASE_TO_EOP);
  1096.     for(i=0; i<cur_voice; i+=10){
  1097.         for(j=0; j<10; j++) {
  1098.             pos_cursor(0, 14+j);
  1099.             scr_func(CLEAR_TO_EOL);
  1100.             if (i+j < cur_voice) 
  1101.                 printf("[%3d] %s", i+j, v_names[i+j]);
  1102.         }
  1103.         printf("\n\r -- hit any key to ");
  1104.         printf("continue or ESC to ");
  1105.         printf("quit listing --");
  1106.         if ((char)Crawcin() == 27) 
  1107.             break;
  1108.     }
  1109.     pos_cursor(0,14);
  1110.     scr_func(ERASE_TO_EOP);
  1111. }
  1112.  
  1113. /* edit: handle edit screen I/O and call appropiate subroutines */
  1114. edit()
  1115. {
  1116.     int    i, j, e_voice, e_max, leng, name_valid, changed, target;
  1117.     int    last_slash, main_drive, start, f_handle;
  1118.     long    drv_map;
  1119.     char    key, voice[TOTAL_SIZE], v_name[80];
  1120.     char    pfname[80], path[80], file[20], main_path[80];
  1121.  
  1122.     changed = FALSE;
  1123.     do {
  1124.         pos_cursor(8, 3+EDIT_OPTIONS);
  1125.         scr_func(ERASE_TO_EOP);
  1126.         switch((int)(key = Crawcin())) {
  1127.         case 'c':
  1128.         case 'C':
  1129.             printf("c\n\r");
  1130.             e_voice = get_v_num(5+EDIT_OPTIONS);
  1131.             if (e_voice == ABORT) break;
  1132.             do {
  1133.                 do {
  1134.                     pos_cursor(0,6+EDIT_OPTIONS);
  1135.                     scr_func(CLEAR_TO_EOL);
  1136.                     printf("enter voice name: \007");
  1137.                     printf("\n\r[ESC to abort]");
  1138.                     pos_cursor(18, 6+EDIT_OPTIONS);
  1139.                     leng = get_str(v_name);
  1140.                 } while (leng == 0);
  1141.                 if (leng < 0) break;
  1142.                 name_valid = TRUE;
  1143.                 for(i=0; i<leng; i++)
  1144.                     if (v_name[i]<32 || v_name[i]>127) {
  1145.                         printf("\n\rName has invalid ");
  1146.                         printf("character in it - ");
  1147.                         printf("re-try");
  1148.                         name_valid = FALSE;
  1149.                         break;
  1150.                     }
  1151.                 if (name_valid)
  1152.                     for(i=0; i<cur_voice; i++) {
  1153.                         if(!strcmp(v_names[i],v_name))
  1154.                         {
  1155.                             printf("\n\rThere is al");
  1156.                             printf("ready a voice");
  1157.                             printf(" named '%s'",
  1158.                                 v_name);
  1159.                             printf(" - re-try");
  1160.                             name_valid = FALSE;
  1161.                             break;
  1162.                         }
  1163.                     }
  1164.             } while(name_valid == FALSE);
  1165.             if (leng < 0) break;
  1166. #ifdef    DX100
  1167.             strncpy(voices[e_voice]+77, v_name, 10); 
  1168.             for(i=strlen(v_name); i<10; i++) 
  1169.                 voices[e_voice][77+i] = ' ';
  1170. #endif
  1171.             strcpy(v_names[e_voice], v_name);
  1172.             changed = TRUE;
  1173.             break;
  1174.         case 'd':
  1175.         case 'D':
  1176.             printf("%c\n\r", key);
  1177.             if (key == 'd')
  1178.                 printf("Delete voice...\n\r");
  1179.             else
  1180.                 printf("Delete from voice...\n\r");
  1181.             e_voice = get_v_num(6+EDIT_OPTIONS);
  1182.             if (e_voice < 0) break;
  1183.             if (key == 'D') {
  1184.                 printf("\n\r");
  1185.                 scr_func(CLEAR_TO_EOL);
  1186.                 printf("up through voice...\n\r");
  1187.                 do {
  1188.                     e_max = get_v_num(8+EDIT_OPTIONS);
  1189.                     if (e_max >= 0 && e_max < e_voice) {
  1190.                         sprintf( out,
  1191.     "\n\rLast voice number must be greater than first voice number [%d]",
  1192.                             e_voice);
  1193.                         warn(out);
  1194.                     }
  1195.                 } while (e_max >= 0 && e_max < e_voice);
  1196.                 if (e_max < 0) break;
  1197.             } else e_max = e_voice;
  1198.             for (i = e_max+1; i < cur_voice; i++) {
  1199.                 strcpy(v_names[e_voice + i - (e_max+1)],
  1200.                     v_names[i]);
  1201.                 voice_copy(voices[e_voice + i - (e_max+1)],
  1202.                     voices[i]);
  1203.             }
  1204.             cur_voice -= e_max+1 - e_voice;
  1205.             changed = TRUE;
  1206.             break;
  1207.         case 'm':
  1208.         case 'M':
  1209.             printf("%c\n\r", key);
  1210.             if (key == 'm')
  1211.                 printf("Move voice...\n\r");
  1212.             else
  1213.                 printf("First voice to move...\n\r");
  1214.             e_voice = get_v_num(6+EDIT_OPTIONS);
  1215.             if (e_voice < 0) break;
  1216.             if (key == 'M') {
  1217.                 printf("\n\r");
  1218.                 scr_func(CLEAR_TO_EOL);
  1219.                 printf("up through voice...\n\r");
  1220.                 do {
  1221.                     e_max = get_v_num(8+EDIT_OPTIONS);
  1222.                     if (e_max >= 0 && e_max < e_voice) {
  1223.                         sprintf( out,
  1224.     "\n\rLast voice number must be greater than first voice number [%d]",
  1225.                             e_voice);
  1226.                         warn(out);
  1227.                     }
  1228.                 } while (e_max >= 0 && e_max < e_voice);
  1229.                 if (e_max < 0) break;
  1230.             } else e_max = e_voice;
  1231.             do {
  1232.                 pos_cursor(0, 5+EDIT_OPTIONS);
  1233.                 scr_func(ERASE_TO_EOP);
  1234.                 if (e_max == e_voice)
  1235.                 printf("move voice %d in front of voice...",
  1236.                         e_voice);
  1237.                 else
  1238.             printf("move voices %d to %d in front of voice...",
  1239.                     e_voice, e_max);
  1240.                 printf("\n\r(End of file is position %d)",
  1241.                     cur_voice);
  1242.                 strcpy(v_names[cur_voice++], "END OF FILE");
  1243.                 target = get_v_num(7+EDIT_OPTIONS);
  1244.                 cur_voice--;
  1245.                 if (target > cur_voice) {
  1246.                     sprintf(out, 
  1247.                     "\n\r\n\rhighest legal position is %d",
  1248.                         cur_voice);
  1249.                     warn(out);
  1250.                 } else if (target > e_voice && target <= e_max){
  1251.                     printf(
  1252.                 "\n\r\n\rblock cannot be moved inside itself!");
  1253.                     sprintf(out,
  1254.             "\n\rLegal ranges are from 0 to %d and from %d to %d",
  1255.                         e_voice, e_max+1, cur_voice);
  1256.                     warn(out);
  1257.                 }
  1258.             } while (target > cur_voice || 
  1259.                 target > e_voice && target <= e_max);
  1260.             if (target < 0) break;
  1261.             printf("\n\rMoving voice(s)...");
  1262.             for (i = e_voice; i < e_max+1; i++) {
  1263.                 if (target > e_max) {
  1264.                     strcpy(v_name, v_names[e_voice]);
  1265.                     voice_copy(voice, voices[e_voice]);
  1266.                     for (j = e_voice+1; j < target; j++) {
  1267.                         strcpy(v_names[j-1],v_names[j]);
  1268.                         voice_copy(voices[j-1],
  1269.                             voices[j]);
  1270.                     }
  1271.                     strcpy(v_names[target-1], v_name);
  1272.                     voice_copy(voices[target-1], voice);
  1273.                 } else {
  1274.                     strcpy(v_name, v_names[i]);
  1275.                     voice_copy(voice, voices[i]);
  1276.                     for (j = i-1; j >=  target+i - e_voice;
  1277.                         j--) {
  1278.                         strcpy(v_names[j+1],v_names[j]);
  1279.                         voice_copy(voices[j+1],
  1280.                             voices[j]);
  1281.                     }
  1282.                     strcpy(v_names[target + i - e_voice],
  1283.                         v_name);
  1284.                     voice_copy(voices[target + i - e_voice],
  1285.                         voice);
  1286.                 }
  1287.             }
  1288.             changed = TRUE;
  1289.             break;
  1290.         case 'r':
  1291.             printf("r\n\r");
  1292.             Dgetpath(main_path, 0);
  1293.             drv_map = Dsetdrv(main_drive = Dgetdrv());
  1294.             do {
  1295.                 name_valid = !E_OK;
  1296.                 warn("Enter disk if necessary");
  1297.                 pos_cursor(0, 5+EDIT_OPTIONS);
  1298.                 scr_func(ERASE_TO_EOP);
  1299.                 printf("[Drive:] Path/File name: ");
  1300.                 printf("\n\r[ESC to abort]");
  1301.                 pos_cursor(25, 5+EDIT_OPTIONS);
  1302.                 if ((leng = get_str(pfname)) < 0) break;
  1303.                 printf("\n\r");
  1304.                 if (pfname[1] == ':') {
  1305.                     if (pfname[0] >= 'a' 
  1306.                         && pfname[0] <= 'z')
  1307.                         pfname[0] += 'A' - 'a';
  1308.                     if (pfname[0] < 'A' || pfname[0] > 'Z'){
  1309.     warn("Bad drive; Drive letter must be in the range A-Z... re-try");
  1310.                         continue;
  1311.                     }
  1312.                     if (!((1L<<(pfname[0]-'A')) & drv_map)){
  1313.                         sprintf(out, 
  1314.                 "Bad drive; Drive '%c' not installed... re-try",
  1315.                             pfname[0]);
  1316.                         warn(out);
  1317.                         continue;
  1318.                     }
  1319.                     Dsetdrv(pfname[0] - 'A');
  1320.                     strcpy(pfname, &pfname[2]);
  1321.                 }
  1322.                 if (pfname[0] == '\\') {
  1323.                     last_slash = 0;
  1324.                     for (i=1; i < leng; i++) 
  1325.                         if (pfname[i] == '\\') 
  1326.                             last_slash = i;
  1327.                     for (i=0; i<last_slash; i++) 
  1328.                         path[i] = pfname[i];
  1329.                     path[last_slash] = '\0';
  1330.                     Dsetpath(path);
  1331.                     strcpy(file, &pfname[last_slash+1]);
  1332.                 }
  1333.                 else strcpy(file, pfname);
  1334.                 if ((name_valid = Fsfirst(file, 0)) != E_OK)
  1335.                     printf("'%s' not found, re-try...\n\r",
  1336.                         pfname);
  1337.                 else printf("'%s' found...", pfname);
  1338.             } while (name_valid != E_OK);
  1339.             if (leng < 0) break;
  1340.             if ((f_handle = Fopen(file, READ)) < 0) {
  1341.                 sprintf(out, 
  1342.                 "Cannot open '%s' for reading -- aborting...",
  1343.                     pfname);
  1344.                 warn(out);
  1345.                 break;
  1346.             }
  1347.             printf("reading in voice data\n\r");
  1348.             while(TRUE) {
  1349.                 if (cur_voice+1 >= VOICES) {
  1350.                     sprintf(out,
  1351.             "voices number limit reached (%d) -- file read aborted",
  1352.                         VOICES);
  1353.                     warn(out);
  1354.                     break;
  1355.                 }
  1356.                 if (scan_name(f_handle, v_names[cur_voice]) 
  1357.                     != OK) break;
  1358.                 if (strlen(v_names[cur_voice]) > 0) {
  1359.                     if (scan_voice(f_handle, 
  1360.                         voices[cur_voice]) != OK) break;
  1361.                     cur_voice++;
  1362.                 }
  1363.                 else break;
  1364.             }
  1365.             Fclose(f_handle);
  1366.             changed = TRUE;
  1367.             warn("Re-insert original disk if necessary");
  1368.             Dsetdrv(main_drive);
  1369.             Dsetpath(main_path);
  1370.             break;
  1371.         case 'x':
  1372.         case 'X':
  1373.             printf("x\n\r");
  1374.             if (changed && save_edit() < 0) break;
  1375.             else key = 'q';
  1376.             break;
  1377.         case 'q':
  1378.         case 'Q':
  1379.             printf("q\n\r");
  1380.             if (!changed) break;
  1381.             printf("Restoring library to pre-edit state from disk\n\r");
  1382.             get_voices(v_names, voices);
  1383.             break;
  1384.         default:
  1385.             printf("\007");
  1386.             printf("Bad option '%c' - re-try", key);
  1387.             break;
  1388.         }
  1389.     } while (key != 'q' && key != 'Q');
  1390. }
  1391.  
  1392. /* save_edit: save the edited voice library, returning a success/failure code */
  1393. int
  1394. save_edit()
  1395. {
  1396.     long    needed_space, lib_size(), *fsize;
  1397.     unsigned char    response;
  1398.  
  1399.     needed_space = lib_size();
  1400.     while (Fsfirst(VOICE_FILE, 0) != E_OK) {
  1401.         printf("'%s' not found.\n\r", VOICE_FILE);
  1402.         warn("Please insert voice disk.");
  1403.     }
  1404.     fsize = Fgetdta() + 26;
  1405.     if (*fsize + cur_space >= needed_space) {
  1406.         return(dump_voices());
  1407.     }
  1408.     else {
  1409.         do {
  1410.             printf("\n\rNot enough room on disk to save ");
  1411.             printf("file\n\rDo you have a formatted disk ");
  1412.             printf("with at least %ld free bytes \n\r",
  1413.                 needed_space);
  1414.             printf("\tavailable to insert (y/n)? ");
  1415.             if ((response = Crawcin()) == 'y') {
  1416.                 printf("y\n\r");
  1417.                 warn("Insert disk");
  1418.                 check_disk();
  1419.                 if (Fsfirst(VOICE_FILE, 0) == E_OK) {
  1420.                     fsize = Fgetdta() + 26;
  1421.                 } else {
  1422.                     fsize = Fgetdta() + 26;
  1423.                     *fsize = 0;
  1424.                 }
  1425.                 if (cur_space + *fsize > needed_space) {
  1426.                     return(dump_voices());
  1427.                     break;
  1428.                 }
  1429.             } else {
  1430.                 printf("n\n\r");
  1431.                 printf("Aborting save...\n\r");
  1432.                 printf("It is recommended that you ");
  1433.                 printf("quit out of this program and ");
  1434.                 printf("\n\rcreate enough space on a ");
  1435.                 printf("disk to save the file as ");
  1436.                 printf("desired\n\r");
  1437.                 printf("Hit any key to continue...");
  1438.                 wait();
  1439.                 break;
  1440.             }
  1441.         } while ((response = Crawcin()) == 'y');
  1442.     }
  1443. }
  1444.  
  1445. /* lib_size: return the size of the voice library (in bytes) */
  1446. long
  1447. lib_size()
  1448. {
  1449.     int    i;
  1450.     long    size;
  1451.         
  1452.     for (i=0, size=0; i < cur_voice; i++) {
  1453.         size += strlen(v_names[i]) + 1;
  1454.         size += TOTAL_SIZE;
  1455.     }
  1456.     return(size);
  1457. }
  1458.  
  1459. /* search: search the voice library names for a match with 's_str', handling
  1460.     special cases in 's_str', starting from voice 'from' */
  1461. int
  1462. search(s_str, from)
  1463. char    *s_str;
  1464. int    from;
  1465. {
  1466.     int    found, target_len;
  1467.     char    ps_str[80], rs_str[80], ss_str[80], srs_str[80];
  1468.  
  1469.     if (extract(s_str, ps_str, rs_str) == NULL) return(from);
  1470.     for (found=from; found < cur_voice; found++) {
  1471.         if (substr(v_names[found], ps_str)) {
  1472.             strcpy(srs_str, rs_str);
  1473.             do {
  1474.                 if (extract(srs_str, ss_str, srs_str) == NULL) 
  1475.                     return(found);
  1476.             } while (substr(v_names[found], ss_str));
  1477.         }
  1478.     }
  1479.     return(found);
  1480. }
  1481.  
  1482. /* extract: break string 'raw_str' into an initial search string ('fs_str')
  1483.     and a remnant string ('rs_str') returning NULL if 'raw_str' is empty,
  1484.     !NULL otherwise */
  1485. int
  1486. extract(raw_str, fs_str, rs_str)
  1487. char    *raw_str, *fs_str, *rs_str;
  1488. {
  1489.     if (*raw_str == '\0') return(NULL);
  1490.     if (*raw_str == AND_CHAR) *raw_str++;
  1491.     while (*raw_str != '\0' && *raw_str != AND_CHAR)
  1492.         *fs_str++ = *raw_str++;
  1493.     *fs_str = '\0';
  1494.     while ((*rs_str++ = *raw_str++) != '\0');
  1495.     return(!NULL);
  1496. }
  1497.  
  1498. /* substr: determine if pattern 'pattern' exists in string 'field',
  1499.     returning TRUE if so, FALSE otherwise */
  1500. int
  1501. substr(field, pattern)
  1502. char    *field, *pattern;
  1503. {
  1504.     int    i, reps, leng;
  1505.     
  1506.     if ((leng = strlen(pattern)) == 0) return(TRUE);
  1507.     reps = strlen(field) - leng;
  1508.     for (i=0; i <= reps; i++) 
  1509.         if (!strncmp(field+i, pattern, leng)) return(TRUE);
  1510.     return(FALSE);
  1511. }
  1512.  
  1513. /* check_disk: determine free space on disk */
  1514. check_disk()
  1515. {
  1516.     struct { long free_c, tot_c, sec_siz, sec_in_c; } disk_info;
  1517.  
  1518.     printf("checking disk usage\n\r");    
  1519.     Dfree(&disk_info, 0);
  1520.     cur_space = disk_info.free_c * disk_info.sec_in_c * disk_info.sec_siz;
  1521. }
  1522.  
  1523. /* dump_voices: actually write the voice library to disk, an error *should*
  1524.     not be possible at this point.  Nonetheless, a success/failure code
  1525.     is returned */
  1526. int
  1527. dump_voices()
  1528. {
  1529.     int    f_handle, i;
  1530.     long    f_start_leng, offset, incr;
  1531.     char    response;
  1532.  
  1533.     if (Fsfirst(VOICE_FILE, 0) != E_OK) f_start_leng = 0;
  1534.     else {
  1535.         f_start_leng = *(long *)(Fgetdta() + 26);
  1536.         Fdelete(VOICE_FILE);
  1537.         printf("'%s' deleted\n\r", VOICE_FILE);
  1538.     }
  1539.     do {
  1540.         if ((f_handle = Fcreate(VOICE_FILE, 0)) < 0) {
  1541.             printf("Cannot create voice file.\n\r");
  1542.             printf("Ensure disk is inserted and ");
  1543.             printf("not write protected.\n\r");
  1544.             printf("Re-try (y/n)? ");
  1545.             if ((response = Crawcin()) == 'y') {
  1546.                 printf("y\n\r");
  1547.                 continue;
  1548.             } else {
  1549.                 printf("n\n\r");
  1550.                 sprintf(out, 
  1551.         "'%s' deleted/not found and current voices NOT saved!",
  1552.                     VOICE_FILE);    
  1553.                 warn(out);
  1554.                 return(BAD);
  1555.             }
  1556.         } else {
  1557.             printf("'%s' created.\n\r", VOICE_FILE);
  1558.             Fclose(f_handle);
  1559.         }
  1560.     } while (f_handle < 0);
  1561.     f_handle = Fopen(VOICE_FILE, READ_WRITE);
  1562.     if (f_handle < 0) {
  1563.         sprintf(out, "Cannot open '%s' -- Aborting save", VOICE_FILE);
  1564.         warn(out);
  1565.         return(BAD);
  1566.     }
  1567.     printf("'%s' opened for reading/writing...\n\r", VOICE_FILE);
  1568.     pos_cursor(0, 24);
  1569.     printf("Saving voice number ");
  1570.     for (i = 0, offset = 0; i < cur_voice; i++) {
  1571.         pos_cursor(20, 24);
  1572.         scr_func(CLEAR_TO_EOL);
  1573.         printf("%d", i);
  1574.         incr = strlen(v_names[i]) + 1;
  1575.         if (Fwrite(f_handle, incr, v_names[i]) < incr)
  1576.             error("Unknown write error on voice file - bye!");
  1577.         offset += incr;
  1578.         if (Fwrite(f_handle, (long) TOTAL_SIZE, voices[i]) < 0)
  1579.             error("Unknown write error on voice file - bye!");
  1580.         offset += TOTAL_SIZE;
  1581.     }
  1582.     cur_space += f_start_leng;
  1583.     cur_space -= offset;
  1584.     Fclose(f_handle);
  1585.     return(OK);
  1586. }
  1587.  
  1588. /* get_v_num: interact with the user to get a voice number and return it
  1589.     (putting prompts at screen line 'curs_y') */
  1590. int
  1591. get_v_num(curs_y)
  1592. int    curs_y;
  1593. {
  1594.     int    v_num;
  1595.  
  1596.     do {
  1597.         pos_cursor(0,curs_y);
  1598.         scr_func(CLEAR_TO_EOL);
  1599.         printf("enter voice number: \n\r");
  1600.         printf("[ESC to abort, RETURN to list, voices 0-%d available]", 
  1601.             cur_voice-1);
  1602.         pos_cursor(20, curs_y);
  1603.         if ((v_num = get_num()) == NULL)
  1604.             list_voices();
  1605.         if (v_num == BAD)
  1606.             printf("\n\r\n\rBad input - re-try");
  1607.     } while (v_num != ABORT &&    
  1608.         (v_num < 0 || v_num >= cur_voice));
  1609.     return(v_num);
  1610. }
  1611.  
  1612. /* func: call the appropiate voice parameter determining function and 
  1613.     return its value */
  1614. int
  1615. func(i,b)
  1616. int    i,b;
  1617. {
  1618.     switch(types[i][b]) {
  1619.     case 1:
  1620.         return(high(ranges[i], tries[i][b]));
  1621.         break;
  1622.     case 2:
  1623.         return(mid(ranges[i], tries[i][b]));
  1624.         break;
  1625.     case 3:
  1626.     default:
  1627.         return(low(ranges[i], tries[i][b]));
  1628.         break;
  1629.     }
  1630. }
  1631.  
  1632. /* get_roll: determine whether func should be called with a normal or
  1633.     weird value and return what func returns */
  1634. int
  1635. get_roll(a)
  1636. int    a;
  1637. {
  1638.     if (Effect) return(func(a,0));
  1639.     else return(func(a,1));
  1640. }
  1641.  
  1642. /* voice_copy: copy voice 'v2' into voice 'v1' */
  1643. voice_copy(v1, v2)
  1644. char    *v1, *v2;
  1645. {
  1646.     int i;
  1647.  
  1648.     for (i=0; i<TOTAL_SIZE; i++) *v1++ = *v2++;
  1649. }
  1650.  
  1651. #ifdef    DX100
  1652. /* round: return the nearest integral frequency ratio to ratio 'freq' */
  1653. int
  1654. round(freq)
  1655. int    freq;
  1656. {
  1657.     if (freq < 2) return(0);
  1658.     if (freq < 6) return(4);
  1659.     if (freq < 9) return(8);
  1660.     if (freq < 12) return(10);
  1661.     if (freq < 15) return(13);
  1662.     if (freq < 18) return(16);
  1663.     if (freq < 21) return(19);
  1664.     if (freq < 24) return(22);
  1665.     if (freq < 27) return(25);
  1666.     if (freq < 30) return(28);
  1667.     if (freq < 33) return(31);
  1668.     if (freq < 36) return(34);
  1669.     if (freq < 38) return(36);
  1670.     if (freq < 41) return(40);
  1671.     if (freq < 45) return(42);
  1672.     if (freq < 64) return(45);
  1673.     return(4);
  1674. }
  1675. #endif
  1676. ə