home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / PROGRAMS / VOICE / VOICE-C.C < prev    next >
C/C++ Source or Header  |  2000-06-30  |  8KB  |  258 lines

  1. /* Note: I'm sure that some of these may be improved
  2.     and would appreciate any feedback */
  3. /* A set of routines to allow a user to program in BDS C words and
  4.    phrases using a VOTRAX SC-01 chip synthesizer. The main functions is
  5.    "talk" which takes a character string argument that looks like phonemes.
  6.    The subroutine "pronounce" does the port I/O and will need to be
  7.    be individually modified, most likely. Read the comments above it */
  8.  
  9. /* written by Mark Zachmann Sept. 5 1981  Version 0.2 */
  10.  
  11. /* main talking functions... what a slow way to do things */
  12.  
  13. /* it reads a character string corresponding to the phoneme descriptions
  14.     in the VOTRAX phoneme chart (page 3 of SC-01 data sheet)
  15.     and decodes them into numbers (type char, though), then says them.
  16.     Note that because it takes a while to talk I say each phoneme 
  17.     seperately, and thus, while saying one phoneme, the next
  18.     can be decoded from the character string input */
  19.  
  20. talk(line)
  21. char *line;
  22. {  while(0!=*line)
  23.      {    pronounce(phoneme(line));    /* transmit to chip */
  24.     while(','!=*line++);        /* increment counter to start
  25.                         of next phoneme */
  26.      }
  27. }
  28.  
  29. /* Subroutine to take a character string and return a number (type char)
  30.     corresponding to the first phoneme found in the string. Returns
  31.     0xFF if no match (although partial matches will have undefined
  32.     results, e.g. O5 may be the same as O1)    */
  33.  
  34. phoneme(line)
  35. char *line;
  36. { switch(*line++) {
  37.     case 'A': switch(*line) 
  38.           {   case '1': return(5);            /* A1 */
  39.           case '2': return(6);            /* A2 */
  40.           case 'Y': return(0x21);        /* AY */
  41.           case 'E': { if (','==*++line) return(0x2e); /* AE */
  42.                 return(0x2f);              /* AE1 */
  43.                 }
  44.           case 'H': { if (','==*++line) return(0x24); /* AH */
  45.                   if('1'==*line) return(0x15);    /* AH1 */
  46.                   return(8);              /* AH2 */
  47.                 }
  48.           case 'W': { if(','==*++line) return(0x3d);  /* AW */
  49.                   if('1'==*line) return(0x13);    /* AW1 */
  50.                 return(0x30);              /* AW2 */
  51.                 }
  52.         }
  53.     case 'B': return(0xe);                /* B */
  54.     case 'C': return(0x10);                /* CH */
  55.     case 'D': { if(','==*line) return(0x1e);    /* D */
  56.             return(0x4);            /* DT */
  57.           }
  58.     case 'E': switch(*line)
  59.             {    case ',': return(0x2c);        /* E */
  60.             case 'R': return(0x3a);        /* ER */
  61.             case '1': return(0x3c);        /* E1 */
  62.             case 'H': switch(*++line) {
  63.                     case ',': return(0x3b); /* EH */
  64.                     case '1': return(2);    /* EH1 */
  65.                     case '2': return(1);    /* EH2 */
  66.                     default: return(0);    /* EH3 */
  67.                         }
  68.             }
  69.     case 'F': return(0x1d);                /* F */
  70.     case 'G': return(0x1c);                /* G */
  71.     case 'H': return(0x1b);                /* H */
  72.     case 'I': switch(*line)
  73.            {    case ',': return(0x27);        /* I */
  74.             case 'U': return(0x36);     /* IU */
  75.             case '1': return(0x0b);     /* I1 */
  76.             case '2': return(0x0a);     /* I2 */
  77.             default: return(9);        /* I3 */
  78.            }
  79.     case 'J': return(0x1a);                /* J */
  80.     case 'K': return(0x19);                /* K */
  81.     case 'L': return(0x18);                /* L */
  82.     case 'M': return(0x0c);                /* M */
  83.     case 'N': if(','==*line)  return(0x0d);        /* N */
  84.                return(0x14);            /* NG */
  85.     case 'O': switch(*line)
  86.            {    case ',': return(0x26);        /* O */
  87.             case '1': return(0x35);     /* O1 */
  88.             case '2': return(0x34);     /* O2 */
  89.             case 'O': { if(','==*++line) return(0x17);  /* OO */
  90.                     return(0x16);    /* OO1 */
  91.                   }
  92.            }
  93.     case 'P': { if(','==*line) return(0x25);    /* P */
  94.             if('0'==*++line) return(3);        /* PA0 */
  95.             return(0x3e);            /* PA1 */
  96.           }
  97.     case 'R': return(0x2b);                /* R */
  98.     case 'S': { if(','==*line) return(0x1f);    /* S */
  99.             if('H'==*line) return(0x11);    /* SH */
  100.             return(0x3f);            /* STOP */
  101.           }
  102.     case 'T': { if(','==*line) return(0x2a);    /* T */
  103.             if(','==*++line) return(0x39);    /* TH */
  104.             return(0x38);            /* THV */
  105.           }
  106.     case 'U': switch(*line)
  107.           {    case ',': return(0x28);        /* U */
  108.             case '1': return(0x37);        /* U1 */
  109.             default: switch(*++line)
  110.                {    case ',': return(0x33); /* UH */
  111.                 case '1': return(0x32); /* UH1 */
  112.                 case '2': return(0x31); /* UH2 */
  113.                 default: return(0x23);  /* UH3 */
  114.                }
  115.           }
  116.     case 'V': return(0x0f);                /* V */
  117.     case 'W': return(0x2d);                /* W */
  118.     case 'Y': { if(','==*line) return(0x29);    /* Y */
  119.             return(0x22);            /* Y1 */
  120.           }
  121.     case 'Z': { if(','==*line) return(0x12);    /* Z */
  122.             return(7);            /* ZH */
  123.           }
  124.     default : return(0xff);        /* error !! */
  125.     }
  126. }
  127.  
  128. /* this is the pronunciation subroutine. It sends a single phoneme
  129.     to the Votrax synthesis chip. I have implemented mine by way of
  130.     the iobyte. When the list device is set to UC3: my BIOS sends
  131.     output to the synthesizer. Thus all handshaking is external
  132.     to  this program. !! You will need to modify either this or your BIOS.
  133.     I suggest the BIOS as then BASIC and etc. stupid compilers can easily
  134.     interface to the chip */
  135.  
  136. pronounce(c)
  137. char(c);
  138. { char iobyt;
  139.   iobyt=bdos(7);    /* read iobyte */
  140.   bdos(8,0xc0);        /* set list to UC3: */
  141.   bios(5,(c|0x80));    /* send character, I set my pitch to 80h always */
  142.   bdos(8,iobyt);    /* reset IOBYTE to whatever it was */
  143. }
  144.  
  145.  
  146.  
  147. /* program to say a number argument 
  148.     assumes unsigned input, and calls itself recusively. Not terribly 
  149.     fast */
  150.  
  151. saynum(numb)
  152. unsigned numb;
  153. { char c,d,some;
  154.   unsigned j;
  155.  
  156.   some=0;        /* nothing said yet */
  157.  
  158. /* first process the 1000's */
  159.   if(0!=(j=numb/1000))
  160.     { saynum(j);    /* Recur to do thousands */
  161.       talk("TH,AH1,W,Z,I1,N,D,PA1,");     /* thousand */
  162.       numb%=1000;    /* continue with left over */
  163.       some=1 ;    /* flag it as having said something */
  164.     }
  165.  
  166. /* now the 100's */
  167.   if(0!=(j=numb/100))
  168.     { saynum(j);    /* recurring */
  169.       talk("H,H,UH,N,D,R,I3,D,PA1,");    /* hundred */
  170.       numb%=100;    /* continue again */
  171.       some=1 ;    /* flag it */
  172.     }
  173.  
  174. /* now separate the 10's off (if > 20)  */
  175.   if((numb>=20)&&0!=(j=numb%10))    /* recur again if not simple */
  176.     { saynum(numb-j);            /* first do the tens case */
  177.       numb=j;                /* now the remainder */
  178.       some=1;
  179.     }
  180.  
  181. /* main non-recursive portion */
  182.   c=numb;        /* turn into a char for speed */
  183.   d=(c>=20)? c/10 : c%10 ;    /* the kernel is here */
  184.   switch(d)
  185.         {    case 1 : { if(c==1)  talk("W,UH1,I3,N,");    /*  1 */
  186.                  else    talk("E1,L,EH1,V,I1,N,");    /* 11 */
  187.                break;
  188.              }
  189.         case 2 : { if(c==20) talk("T,PA0,W,EH2,N,");    /* 20 */
  190.               else if(c==12) talk("T,PA0,W,EH2,UH2,L,V,");  /* 12 */
  191.               else         talk("T,PA0,U,W,");    /*  2 */
  192.                break;
  193.              }               
  194.         case 3 : { if(c==3)   talk("TH,R,E1,Y,");    /* 3 */
  195.                   else    talk("TH,UH2,ER,");    /* 13,31 */
  196.                break ;
  197.              }
  198.         case 4 : { if(c==4)   talk("F,O,ER,");        /* 4 */
  199.                   else    talk("F,O1,R,");        /* 14,41 */
  200.                break;
  201.              }
  202.         case 5 : { if(c==5)   talk("F,AH1,Y1,V,");    /* 5 */
  203.                   else    talk("F,I1,F,");        /* 15,51 */
  204.                break;
  205.              } 
  206.         case 6 : talk("S,I,K,S,");  break;        /* 6's */
  207.         case 7 : talk("S,EH,V,I3,N,");   break;        /* 7's */
  208.         case 8 : talk("A1,Y,T,");  break ;        /* 8's */
  209.         case 9 : talk("N,AH2,Y,N,");  break ;        /* 9's */
  210.         case 0 : {  if(c==10)  talk("T,EH,N,");        /* 10 */
  211.               else  if(!some) talk("Z,E1,R,O1,W,");    /* 0 */
  212.                 break ;
  213.               }
  214.         }
  215.     if(c>=20) talk("STOP,T,E1,PA0,");            /* ty */
  216.     else if(c>12) talk("STOP,T,E1,E1,N,PA0,");        /* teen */
  217.     else talk("PA1,");    /* done */
  218.     }
  219.  
  220. /*   */
  221. /* says the day of the week, 0 is sunday 6 is saturday */
  222.  
  223. sayday(dayow)
  224. char dayow;
  225. { switch(dayow) {
  226.     case 0: talk("S,UH,N,N,"); break;
  227.     case 1: talk("M,UH,N,"); break;
  228.     case 2: talk("T,PA0,U,EH3,Z,STOP,"); break;
  229.     case 3: talk("W,EH,N,Z,"); break;
  230.     case 4: talk("TH,U1,ER,Z,"); break;
  231.     case 5: talk("F,R,AH1,Y,"); break;
  232.     case 6: talk("S,AE1,EH3,T,ER,"); break;
  233.     default: talk("H,W,UH,T,"); break;        /* what? */
  234.         }
  235.   talk("D,A1,AY,Y1,STOP,STOP,");                /* day */
  236. }
  237.  
  238. /*  */
  239. /* says the month desired */
  240. saymonth(month)        /* month 0-January...11-December */
  241. char(month);
  242. { switch(month) {
  243.     case 0: talk("D,J,I3,AE1,UH2,N,Y,IU,U1,W,AE1,EH3,R,Y,"); break;
  244.     case 1: talk("F,EH1,B,Y,IU,U1,W,AE1,EH3,R,Y,"); break;
  245.     case 2: talk("M,AH2,ER,T,CH,"); break;
  246.     case 3: talk("A1,AY,P,R,OO1,L,"); break;
  247.     case 4: talk("M,A,Y,"); break;
  248.     case 5: talk("D,J,U1,U,N,"); break;
  249.     case 6: talk("D,J,U1,UH3,L,AR1,E1,"); break;
  250.     case 7: talk("AW,G,UH3,S,T,"); break;
  251.     case 8: talk("S,EH1,P,STOP,T,EH1,EH2,M,B,R,"); break;
  252.     case 9: talk("AH1,K,STOP,T,O,W,B,R,"); break;
  253.     case 10: talk("N,O1,W,PA0,V,EH,M,B,R,"); break;
  254.     case 11: talk("D,I2,Y,S,EH,M,B,R,"); break;
  255.     default: talk("H,W,UH,T,"); break;
  256.         }
  257. }
  258.