home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / devices / narratordevice / narratordevice.doc < prev    next >
Text File  |  1995-02-27  |  43KB  |  1,215 lines

  1. 5    NARRATOR DEVICE
  2.  
  3. 5.1  INTRODUCTION
  4.  
  5. The Amiga can not only produce crisp clear four channel stereo
  6. sound, it can even speak. The operating system was designed so
  7. this unique feature easily and efficiently can be used. With
  8. very little effort you can let the Amiga read information.
  9.  
  10. Sadly very few programs use this extremely useful feature.
  11. Although artificial speech sounds a bit monotone and
  12. uninteresting it can be used in many situations to transfer
  13. information from the computer to the user.
  14.  
  15. Imagine if the user has to check hundreds of different numbers
  16. on the screen when the original numbers are on papers. This
  17. very boring and slow task can be made much easier if the Amiga
  18. automatically reads the values and the user only has to look at
  19. the paper.
  20.  
  21.  
  22.  
  23. 5.2  ARTIFICIAL SPEECH
  24.  
  25. Imitating human speech is a very difficult process. Even the
  26. most sophisticated super computers can still not manage to
  27. produce all the different intonations and sounds as a real
  28. human voice can. The Amiga's synthesized speech mechanism is
  29. not at all as powerful as what these super computers have, but
  30. compared to other home computers, it is outstanding.
  31.  
  32. Producing artificial speech on the Amiga can be divided into
  33. two steps:
  34.  
  35.   1. First we have to convert the text we want to be read into
  36.      phonetical text. Phonetical text is written as the words
  37.      should sound and not as how the words are spelled.
  38.      
  39.      If you open a dictionary you will notice that there exist
  40.      a specification on how every word should be pronounced.
  41.      The special symbols used to tell you how the word should
  42.      sound are usually called "the phonetic symbols", and are
  43.      defined in the beginning or end of the dictionary. The
  44.      pronunciation of all words can be constructed with help
  45.      of these symbols.
  46.      
  47.      On the Amiga we use the same technique. However, since the
  48.      real phonetical symbols are very strange and can not be
  49.      typed with a normal keyboard, we use a special
  50.      "computerised" version of these symbols See next section
  51.      for a complete list of these phonetical symbols.
  52.      
  53.      A great news is that you do not have to write the text
  54.      with the phonetical language. You can instead use a
  55.      special function called Translate() which can be found in
  56.      a the "Translator Library". This function can
  57.      automatically convert english text into phonetics.
  58.  
  59.   2. After you have created a string with the phonetical text
  60.      you send it to the "Narrator Device" which will transform
  61.      the phonetical symbols into sound, and the text is read.     
  62.  
  63.  
  64.  
  65. 5.2.1  PHONETIC SYMBOLS
  66.  
  67. The phonetical symbols used by the dictionaries can sadly not
  68. be used on normal computers since they use very strange
  69. signs that can not be reproduced on normal keyboards. Instead
  70. we have to use a special computerized set phonetical symbols
  71. which is defined like this:
  72.  
  73.   Sound  Phoeme  Example  Type
  74.   ---------------------------------
  75.   A      AE      Hat      Vowel
  76.          AO      Talk     Vowel
  77.          EY      Page     Diphthong   (A diphtong is a union
  78.   ---------------------------------   of two vowel sounds or
  79.   B      B       Bad      Consonant   vowel letters.)
  80.   ---------------------------------
  81.   C      CH      Chin     Consonant
  82.          K       Car      Consonant
  83.   ---------------------------------
  84.   D      D       Did      Consonant
  85.   ---------------------------------
  86.   E      EH      Ten      Vowel
  87.          IY      Feet     Vowel
  88.   ---------------------------------  
  89.   F      F       Four     Consonant
  90.   ---------------------------------  
  91.   G      G       Got      Consonant
  92.   ---------------------------------  
  93.   H      /H      How      Consonant
  94.   ---------------------------------  
  95.   I      AY      Five     Diphthong
  96.          ER      Fur      Vowel
  97.          IH      Sit      Vowel
  98.   ---------------------------------  
  99.   J      J       Yes      Consonant
  100.   ---------------------------------  
  101.   K      K       Cat      Consonant
  102.   ---------------------------------  
  103.   L      L       Leg      Consonant
  104.   ---------------------------------  
  105.   M      M       Man      Consonant
  106.   ---------------------------------  
  107.   N      N       No       Consonant
  108.          NX      Sing     Consonant
  109.   ---------------------------------  
  110.   O      AA      Got      Vowel
  111.          AW      Now      Diphthong
  112.          AX      About    Vowel
  113.          IX      Solid    Vowel
  114.          OH      Saw      Vowel
  115.          OW      Home     Diphthong
  116.          OY      Join     Diphthong
  117.          UH      Put      Vowel
  118.   ---------------------------------  
  119.   P      P       Pen      Consonant
  120.   ---------------------------------  
  121.   Q      K       Cat      Consonant
  122.   ---------------------------------  
  123.   R      R       Red      Consonant
  124.   ---------------------------------  
  125.   S      S       Sit      Consonant
  126.          SH      She      Consonant
  127.   ---------------------------------  
  128.   T      DH      Then     Consonant
  129.          T       Tea      Consonant
  130.          TH      Thin     Consonant
  131.   ---------------------------------  
  132.   U      AH      Cup      Vowel
  133.          UW      Too      Diphthong
  134.   ---------------------------------  
  135.   V      V       Voice    Consonant
  136.   ---------------------------------  
  137.   W      W       Wet      Consonant
  138.   ---------------------------------  
  139.   X      /C      Loch     Consonant
  140.   ---------------------------------  
  141.   Y      Y       Yellow   Consonant
  142.   ---------------------------------  
  143.   Z      Z       Zoo      Consonant
  144.          ZH      Vision   Consonant
  145.   ---------------------------------  
  146.  
  147. For example, the word "hello" can phonetically be written as
  148. "/HEHLOW", and the word "house" as "/HAWZ".
  149.  
  150.  
  151.  
  152. 5.2.2  INTONATION
  153.  
  154. When you are speeking you do not use the same voice all the
  155. time. Some parts of the words or sentences are stressed by
  156. using a higher voice, were other parts are prounounced more
  157. softly.
  158.  
  159. For example, the letter "e" in the word "hello" is usually
  160. prounounced in a higher voice. By stressing some words the text
  161. will sound more interesting, and if used with care it can be a
  162. very effective way to get the user's attention.
  163.  
  164. Futhermore, by stressing different parts of a sentence the
  165. whole meaning of the sentence can change quite dramatically.
  166. Take the sentence "I will go home" for example. By stressing
  167. different words the user will interpretate the meaning
  168. differently. With these four words we can actually get five
  169. rather different meanings:
  170.  
  171.   1. If no stressin is used, the meaning is simply that the
  172.      person is going home.
  173.   
  174.   2. By stressing the first word "I" it now sounds like the
  175.      person him/her self is going home but the other persons
  176.      (if there are any) may do something differently.
  177.   
  178.   3. By stressing the second word "will" it now sounds like
  179.      the persons is really determined and that he/she really
  180.      wants to go home.
  181.      
  182.   4. If the person stresses the third word "go" he/she means
  183.      that he/she will walk home, although the word "go" can
  184.      mean travelling by car, train etc.
  185.  
  186.   5. Finally, if the last word is stressed the person wants
  187.      to go to his/her home, and not any other place.
  188.  
  189.  
  190. To stress parts of a word you can put a single digit directly
  191. after the phonem which should use a higher intonation. The
  192. digit 0 means no special intonation, while the higher digit
  193. the more stressed will the phonem be. The digit 9 should be
  194. used when you want maximum intonation.
  195.  
  196. For example, the stress the letter "e" in the word "hello" the
  197. phonetically string should be written as "/HEH4LOW". The
  198. phonem "EH" will then be medium stressed.
  199.  
  200.  
  201.  
  202. 5.2.3  PUNCTATION AND SPECIAL SYMBOLS
  203.  
  204. There exist some symbols which are used to help the reader to
  205. use the righ intonations. The most commonly used symbole is the
  206. puncation ".", but others are the question mark "?", the comma
  207. ",", dash "-", etc... Most of these common punctations are
  208. understod by the Amiga, and will automatically alter the
  209. intonation and speed correctly.
  210.  
  211. Here are the symbols you may use:
  212.  
  213.  
  214.   Type         Symbol  How it affects the intonation
  215.   ------------------------------------------------------------
  216.   Punctation     .     This will make the intonation of the
  217.                        last word a bit softer, and there will
  218.                        be a long pause before any following
  219.                        words are read.
  220.  
  221.   Question mark  ?     This will cause the Amiga to increase
  222.                        the intonation of the last word so it
  223.                        sounds like a question, and it will be
  224.                        followed by long pause before any
  225.                        following words are read.
  226.   
  227.   Comma          ,     The comma is used to divide a sentense
  228.                        into several parts, but putting a small
  229.                        pause before the following text.
  230.   
  231.   Dash           -     The dash can be used as the comma, and
  232.                        works much in the same way. There exist
  233.                        a lot of confusing rules on when the
  234.                        dash and when the comma should be used,
  235.                        but I do not intead to expalin it here.
  236.                        (Mainly because I do not know anything
  237.                        about these rules, sadly. I use what
  238.                        looks best, which I think is an
  239.                        excellent rule.) 
  240.  
  241.   Parentheses    ( )   Parantheses are used to explain
  242.                        something which is not so important that
  243.                        it has to be in the main sentense, but
  244.                        is can still be important for the
  245.                        reader. The text inside parantheses
  246.                        starts off by using less intonation than
  247.                        the rest of the sentense.
  248.  
  249.  
  250.  
  251. 5.2.4  VOLUME
  252.  
  253. Although the intonation is altering the volumne a little, most
  254. of the text will be read with the same volume. You can however
  255. tell the narrator device to use a completely different volume,
  256. and this can be very effective. If you normally use a soft
  257. voice, but suddenly increase it to the maximum the user will
  258. not miss that part.
  259.  
  260. Producing the correct sound can take some time, but once you
  261. have mastered it, the text will sound rather smooth and,
  262. although a bit computerized, rather human. 
  263.  
  264.  
  265.  
  266. 5.3  CONVERT TEXT INTO PHONETIC SYMBOLS
  267.  
  268. Converting text into phonetical symbols does not have to be a
  269. hard task. If you are going to read an English text (or
  270. American, Irish, Scottish etc...) you can use the Translate()
  271. function. It will automatically convert the text into (almost)
  272. correct phonetics which can be used.
  273.  
  274. The Translate() function is located in the "Translator" library
  275. which must be opened before you can use the function. The
  276. Translate() function is actually the only function in this
  277. library.
  278.  
  279.  
  280.  
  281. 5.3.1  OPEN THE TRANSLATOR LIBRARY
  282.  
  283. To open the translator library you declare a global pointer
  284. to it which must be called "TranslatorBase", and you then call
  285. the function OpenLibrary() to open it.
  286.  
  287.   Synopsis:    library_ptr = OpenLibrary( name, revision );
  288.  
  289.   library_ptr: (struct Library *) If the function could open
  290.                the library it returns a pointer to it, else
  291.                NULL is returned. The translator library is
  292.                located on the system disk, and is therefore
  293.                loaded when needed. If some other program
  294.                already has opened it has already been loaded
  295.                into memory and a pointer is immediately
  296.                returned to it.
  297.                
  298.                Be careful to close the library before your
  299.                program terminates. If you forget it, the
  300.                library will remain in the memory until the
  301.                computer is switched off.
  302.   
  303.   name:        (char *) Pointer to a string containing the
  304.                name of the library you want to open. When
  305.                you open the translator library, the name
  306.                should be "translator.library".
  307.   
  308.   revision:    (long) This value tells the Amiga which oldest
  309.                version may be used. If there exist a library
  310.                with the same or higher value the function will
  311.                successfully open the library, else NULL is
  312.                returned. If you simply want any version, set
  313.                this field to zero.
  314.  
  315.  
  316. Here is an example: (Remember that the pointer to the
  317. translator library must ALWAYS be called "TranslatorBase"!)
  318.   
  319.   /* Pointer to the translator library: */
  320.   struct Library *TranslatorBase;
  321.  
  322.   /* Open the library: */
  323.   TranslatorBase = OpenLibrary( "translator.library", 0 );
  324.  
  325.   /* Have we successfully opened it? */
  326.   if( !TranslatorBase )
  327.     clean_up( "Could not open the translator library!" );
  328.  
  329.  
  330.  
  331. 5.3.2  TRANSLATE TEXT
  332.  
  333. Once you have opened the translator device you may start to
  334. use the Translate() function. This function will work best
  335. with English sentences, but can be used for many other
  336. languages if you afterwards do some small changes of the
  337. phonetic text.
  338.  
  339.   Synopsis:  char_left = Translate( in, in_len, out, out_len );
  340.  
  341.   char_left: (long) If not all phonetic text could fit in the
  342.              out string the function will automatically only
  343.              translate the words which will fit. (It will not
  344.              stop in the middle of a word.) If all words could
  345.              be translated zero is returned, else a negative
  346.              value is returned. This value tells us how many
  347.              letters of the "in" string have been translated.
  348.              With this value we can then call the function
  349.              again and translate the remaining text.
  350.              
  351.              Note that the number is negative.
  352.              
  353.   in:        (char *) Pointer to the (English) text string
  354.              which should be read.
  355.  
  356.   in_len:    (long) The length of the (English) text string.
  357.  
  358.   out:       (char *) Pointer to a string where the phonetic
  359.              text string will be stored. (The "in" string is
  360.              converted and copied to the "out" string.)
  361.              
  362.   out_len:   (long) The length of the phonetic (out) string.
  363.  
  364.  
  365. Here is an example on how to translate a string. The nice thing
  366. is that we can translate strings of any size. If the translated
  367. string does not fit in the buffer, we divide it up into smaller
  368. parts.
  369.  
  370.   /* Translated buffer size: */
  371.   #define PHONETIC_BUFFER_SIZE 50
  372.  
  373.   /* Number of characters that were translated, or */
  374.   /* zero if all characters were translated:       */
  375.   int char_translated;
  376.   
  377.   /* This variable contains the current position */
  378.   /* in the string which is translated:          */
  379.   int current_position;
  380.    
  381.   /* The original string: */
  382.   char *original_string = "The Amiga C Encyclopedia!";
  383.   
  384.   /* The phonetic string: */
  385.   char phonetic_string[ PHONETIC_BUFFER_SIZE ];
  386.  
  387.  
  388.   /* Open the translator library: */
  389.   TranslatorBase = (struct Library *)
  390.     OpenLibrary( "translator.library", 0 );
  391.  
  392.   /* Have we successfully opened the library? */
  393.   if( !TranslatorBase )
  394.     clean_up( "Could not open the translator library!" );
  395.  
  396.  
  397.   /* Start with the first character in the original string: */
  398.   current_position = 0;
  399.   
  400.   /* Translate (parts of) our string into phonetics: */
  401.   char_translated =
  402.     Translate( original_string,
  403.                strlen( original_string ),
  404.                phonetic_string,
  405.                PHONETIC_BUFFER_SIZE );
  406.  
  407.   /* Print the translated part: */
  408.   printf( "%s\n", phonetic_string );
  409.  
  410.  
  411.   /* As long as Translate() does not return zero we stay */
  412.   /* in this while loop and continues to translate the   */
  413.   /* original string into phonetics:                     */
  414.   while( char_translated )
  415.   {
  416.     /* Increase the current position in the original string:  */
  417.     /* (Remember that "char_translated" variable is negative, */
  418.     /* and we must therefore use the "-=" operator and not    */
  419.     /* the "+=" to increase the current position.[-- = +])    */
  420.     current_position -= char_translated;
  421.  
  422.     /* Translate the following part our string into phonetics: */
  423.     /* (Note that when we put brackets after a string we we    */
  424.     /* get the character at the specified position, but since  */
  425.     /* we want the address of that position we also have to    */
  426.     /* put the pointer "&" sign in front of the string.)       */
  427.     char_translated =
  428.       Translate( &original_string[ current_position],
  429.                  strlen( &original_string[ current_position] ),
  430.                  phonetic_string,
  431.                  PHONETIC_BUFFER_SIZE );
  432.  
  433.     /* Print the translated part: */
  434.     printf( "%s\n", phonetic_string );
  435.   }
  436.  
  437.   /* All words have now been translated! */
  438.  
  439.  
  440.  
  441. 5.3.3  CLOSE THE TRANSLATOR LIBRARY
  442.  
  443. Before your program terminates it must close the translator
  444. library. This is especially important with this library since
  445. it is loaded from the system disk when opened, and if you do
  446. not close it a lot of memory is wasted. Be careful about this.
  447.  
  448. As I have said many times, make sure that your program does not
  449. only terminate nicely when it has reached the end. It must also
  450. manage to terminate nicely if it suddenly has to quit because of
  451. some error. If you look at the examples which accompanies this
  452. manual you will see that most of them use a function called
  453. "clean_up()". The idea with this function is that it examines
  454. all resources, and if it finds out that something has been
  455. opened or allocated it closes it before the program terminates.
  456. Because it examines all the resources before it attempts to
  457. close or deallocate them the function can always be called and
  458. it will clean up everything, even if you only have opened and
  459. allocated some resources. Try to use something similar in your
  460. own programs.
  461.  
  462.  
  463.  
  464. 5.4  READ PHONETIC SYMBOLS
  465.  
  466. The translator library and the function Translate() are only
  467. used to convert normal (English) text into phonetical strings.
  468. These phonetical strings can then be read by the Amiga, but to
  469. do this you have to use another resource on the Amiga which is
  470. the famous "Narrator Device". (Tataaa, trumpets and drums!) 
  471.  
  472. The narrator device is very straight forward and easy to use.
  473. As always you use request blocks to send your commands, and the
  474. device will reply by sending messages to a reply (message)
  475. port. The device should of course first be opened by calling
  476. the OpenDevice() function. When your program wants to terminate
  477. the device and message port are closed and the request block
  478. is deallocated.
  479.  
  480.  
  481.  
  482. 5.4.1  NARRATOR REQUEST BLOCK
  483.  
  484. When you are using the narrator device you have to use an
  485. extended request block called "narrator_rb" which is defined
  486. like this: (Defined in header file "devices/narrator.h".)
  487.  
  488. struct narrator_rb
  489. {
  490.   struct IOStdReq message;
  491.   UWORD  rate;
  492.   UWORD  pitch;
  493.   UWORD  mode;
  494.   UWORD  sex;
  495.   UBYTE  *ch_masks;
  496.   UWORD  nm_masks;
  497.   UWORD  volume;
  498.   UWORD  sampfreq;
  499.   UBYTE  mouths; 
  500.   UBYTE  chanmask;
  501.   UBYTE  numchan;
  502.   UBYTE  pad;
  503. };
  504.  
  505. message:   The top part of this request block consists of the
  506.            standard input output request block. This IOStdReq
  507.            block is explained below.
  508.  
  509. rate:      The speaking rate in words per minute. The default
  510.            rate (DEFRATE) has been defined as 150 words per
  511.            minute. The maximum speed (MAXRATE) is 400 words and
  512.            the minimum speed (MINRATE) is 40 words per minute.
  513.  
  514. pitch:     The voice's pitch. This is the medium pitch value.
  515.            Stressed words are spoken with a higher pitch, while
  516.            soft words are spoken with a lower pitch. By
  517.            changing this value the whole voice is affected.
  518.  
  519.            The default pitch (DEFPITCH) is 110. The maximum
  520.            pitch (MAXPITCH) is 320 and the minimum pitch is 65.
  521.  
  522. mode:      This value will affect the way the text is read. If
  523.            you set the flag "NATURALF0" the voice will go up
  524.            and down as the text is read. On the other hand, if
  525.            you set the flag "ROBOTICF0" the voice will be very
  526.            dull and does not change as the text is read.
  527.  
  528. sex:       If the flag "MALE" is set a dark male voice will be
  529.            used. If you instead set the flag "FEMALE" a lighter
  530.            and sharper voice will be used. (Do not ask me why
  531.            they did not define it as "BITCH".)
  532.  
  533. *ch_masks: This field should be given a pointer to an
  534.            "allocation array" which specifies which audio
  535.            channels that should be used.
  536.            
  537.            There exist four sound channels which can be used.
  538.            The first and last sound channel is connected to the
  539.            left audio port, while the second and third is
  540.            connected to the right audio port.
  541.  
  542.            To specify which channels you want to use you use
  543.            a value where the first bit represents the first
  544.            sound channel, the second bit the second sound
  545.            channel and so on...
  546.  
  547.              Bit:         3     2      1      0
  548.              -------------------------------------
  549.              Value:       8     4      2      1
  550.              Channel:     3     2      1      0
  551.              Audio port:  Left  Right  Right  Left
  552.  
  553.            To reserve the first and last channel (both using
  554.            the left sound channel) you would use the value 9
  555.            (1001[bin] = 9[dec]). To reserve the second and
  556.            third channel (both using the right sound channel)
  557.            you would use the value 6 (0110[bin] = 6[dec]).
  558.            To reserve all four sound channels set the value to
  559.            15 (1111[bin] = 15[dec]).
  560.            
  561.            The allocation array should consist of all the
  562.            channel combinations you like. The narrator device
  563.            will first try to reserve the channels specified by
  564.            the first value. If it could not get these channels,
  565.            it tries the next values until if finds a
  566.            combination it could reserve or it reaches the end
  567.            of the allocation array and the operation fails.
  568.            
  569.            For example. If you want that the text should be
  570.            read in stereo you have to use one audio channel
  571.            from the right and one from the left port. There
  572.            exist four possible combinations which satisfy this,
  573.            and the "allocation array" should therefore look
  574.            like this:
  575.            
  576.              UBYTE allocation_array = { 3, 5, 10,12 };
  577.  
  578.              Dec    Bin     Description
  579.              ---------------------------------------------------
  580.                3    0011    First left and first right channel.
  581.                5    0101    First left and second right channel.
  582.               10    1010    Second left and first right channel.
  583.               12    1100    Second left and second right channel.
  584.  
  585. nm_masks:  This field should be given a number which tells the
  586.            narrator device how many values there are in the
  587.            allocation array. 
  588.  
  589. volume:    The volume of the voice. The default volume (DEFVOL)
  590.            is the same as the maximum volume (MAXVOL) which is
  591.            defined as 64. The minimum volume (MINVOL) is 0
  592.            which is the same thing as silent.
  593.            
  594.            I myself does not like that the maximum volume is
  595.            often used. It would be much better if everyone were
  596.            using the medium volume as the default value. The
  597.            user will then turn up the volume on his/her stereo
  598.            to compensate for the lower volume. The advantage is
  599.            that if you now suddenly play a very loud sound or
  600.            use a very loud voice it will also be very loud.
  601.            
  602.            Imagine a game which is normally using a sound level
  603.            of 32. The user is sitting alone in his/her own room,
  604.            and it is very late. Imagine what would happen if a
  605.            monster would appear in the the game and at the same
  606.            time the volume was increased to maximum. It will
  607.            undoubtedly be a nice (hmmm) surprise for the user.
  608.  
  609. sampfreq:  This field specifies which frequency should be used.
  610.            The default frequency (DEFFREQ) is 22200. The
  611.            maximum value (MAXFREQ) is 28000 and the minimum
  612.            value (MINFREQ) is 5000. 
  613.  
  614. mouths:    Normally this field should be set to zero. However,
  615.            of you are going to use the "mouth" request, as
  616.            explained below, you should set a non zero value.
  617.  
  618. chanmask:  This field contains the value which was used of the
  619.            allocation array to reserve the audio channel(s).
  620.            This field is used by the system, but if you like
  621.            you may examine it, but you may never change it.
  622.  
  623. numchan:   Number of channels used. This field is also used by
  624.            the system, but if you like you may examine it, but
  625.            you may never change it.
  626.  
  627. pad:       This field is not used, and should therefore never
  628.            be used.
  629.  
  630.  
  631. The IOStdReq structure (which is a part of the narrator_rb
  632. structure) is defined in the "exec/io.h" header file like this:
  633. (Only some parts of this structure will be used, so you do not
  634. have bother too much about it.)
  635.  
  636. struct IOStdReq
  637. {
  638.   struct Message io_Message;
  639.   struct Device  *io_Device;
  640.   struct Unit    *io_Unit;
  641.   UWORD  io_Command;
  642.   UBYTE  io_Flags;
  643.   BYTE   io_Error;
  644.   ULONG  io_Actual;
  645.   ULONG  io_Length;
  646.   APTR   io_Data;
  647.   ULONG  io_Offset;
  648. };
  649.  
  650. io_Message: The top part consists of a Message structure which
  651.             will be sent to us when the request has been
  652.             completed (successfully or not). This message
  653.             structure will automatically be given a pointer to
  654.             the reply port when the narrator_rb structure is
  655.             created, and the priority will automatically be set
  656.             when used, so we do not have to bother too much
  657.             about it.
  658.  
  659. io_Device:  This field will automatically be initialized when
  660.             you use this request block together with an
  661.             OpenDevice() function call. It is simply a pointer
  662.             to the device which this request block is made for.
  663.  
  664. io_Unit:    This field will automatically be initialized when
  665.             you send the request block to the narrator device.
  666.  
  667. io_Command: The following commands are accepted by the narrator
  668.             device, and may be used: (Will be explained below.)
  669.  
  670.               CMD_WRITE       Start to speak.
  671.               CMD_STOP        Stop all speech requests.
  672.               CMD_START       Start to speak again.
  673.               CMD_FLUSH       Remove all queued requests.
  674.               CMD_RESET       Reset the narrator device.
  675.  
  676. io_Flags:   No flags are used.
  677.  
  678. io_Error:   If the request can not successfully be executed by
  679.             the narrator device, it will be returned with one
  680.             of the following error flags:
  681.  
  682.               ND_NoMem     Not enough memory for the request.
  683.               ND_NoAudLib  Can not open the audio device.
  684.               ND_MakeBad   Can not execute the MakeLibrary()
  685.                            function.
  686.               ND_UnitErr   Wrong unit number (not 0).
  687.               ND_CantAlloc Can not find any free audio channels
  688.                            to reserve.
  689.               ND_Unimpl    Not a valid command.
  690.               ND_NoWrite   Nothing is being read, so you can
  691.                            not read any "mouth" values.
  692.               ND_Expunged  Wrong expunge value.
  693.               ND_PhonErr   Wrong phonetic code.
  694.               ND_RateErr   Too large or small rate value
  695.               ND_PitchErr  Too large or small pitch value
  696.               ND_SexErr    Wrong sex number used.
  697.               ND_ModeErr   Wrong mode value used.
  698.               ND_FreqErr   Too high or low frequency value.
  699.               ND_VolErr    Too high or low volume value.
  700.  
  701. io_Actual:  Used by the system.
  702.  
  703. io_Length:  The number of characters in the phonetic string
  704.             that should be read.
  705.  
  706. io_Data:    Pointer to the phonetic sting.
  707.  
  708. io_Offset:  Used by the system.
  709.  
  710.  
  711.  
  712. 5.4.2  OPEN THE NARRATOR DEVICE
  713.  
  714. To open the narrator device does not differ from opening other
  715. devices. First you have to create a message port to which the
  716. device can send messages to you. Secondly you have to create
  717. one or more narrator_rb structures by using the CreateExtIO()
  718. function. Finally you can open the narrator device with help
  719. of one of the request blocks.
  720.  
  721.   1. Open a message port. Since it is only our task and the
  722.      narrator device that will use the message port, we do not
  723.      need to make it "public", therefore no name. Priority
  724.      should as usual be set to 0, normal priority.
  725.  
  726.        struct MsgPort *replymp;
  727.  
  728.        replymp = (struct MsgPort *)
  729.          CreatePort( NULL, 0 );
  730.  
  731.        if( !replymp )
  732.          clean_up( "Could not create the reply port!" );
  733.  
  734.  
  735.   2. Allocate a request block of type narrator_rb structure.
  736.      The narrator_rb structure is an extended version of the
  737.      normal request block, and should therefore be allocated
  738.      with help of the CreateExtIO() function with the size
  739.      set to sizeof( struct narrator_rb ).
  740.  
  741.        struct narrator_rb *narrator_req;
  742.  
  743.        narrator_req = (struct narrator_rb *)
  744.          CreateExtIO( replymp, sizeof( struct narrator_rb ) );
  745.  
  746.        if( !narrator_req )
  747.          clean_up( "Not enough memory!" );
  748.  
  749.  
  750.   3. Once the message port and the request block have
  751.      successfully been created you can "open" (gain access to)
  752.      the narrator device. The default values will now also be
  753.      set in the request block.
  754.  
  755.        error = OpenDevice( "narrator.device", 0, narrator_req, 0 );
  756.  
  757.        if( error )
  758.          clean_up( "Could not open the Narrator Device!" );
  759.  
  760.  
  761.  
  762. 5.4.3  READ PHONETIC TEXT 
  763.  
  764. Once you have successfully opened the narrator device you may
  765. start to use the narrator device. The fields of the request
  766. block with which the narrator device was opened with have
  767. automatically been given the default values:
  768.  
  769.   1. The rate is set to 150 words per minute.
  770.   2. The pitch is set to 110 Hz.
  771.   3. The mode is set to normal (living) voice.
  772.   4. The sex field is set to man.
  773.   5. The sampfreq is set to 22200.
  774.   6. The volume is set to 64.
  775.  
  776. The following fields must be initialized by yourself:
  777.  
  778.   1. You must give the "io_Data" field of the IOStdReq
  779.      structure a pointer to the string of phonetic words that
  780.      should be read.
  781.   
  782.   2. Give the "io_Length" field of the IOStdReq structure the
  783.      number of translated characters that should be read.
  784.      You can use the function strlen() to find out how long
  785.      the translated string is.
  786.  
  787.   3. You have to give the "ch_masks" field a pointer to the
  788.      allocation array that should be used.
  789.  
  790.   4. Give the "nm_masks" field the number of values which exist
  791.      in the allocation array.
  792.  
  793.   5. Finally you should give the "io_Command" field of the
  794.      IOStdReq structure the "CMD_WRITE" flag. (We are going to
  795.      send [write] text to the narrator device.)
  796.  
  797.  
  798. Here is an example:
  799.  
  800.  
  801.   /* The text should be read in stereo: */
  802.   UBYTE allocation_array[]=
  803.   {
  804.     LEFT0F|RIGHT0F, /* First left and first right channel.   */
  805.     LEFT0F|RIGHT1F, /* First left and second right channel.  */
  806.     LEFT1F|RIGHT0F, /* Second left and first right channel.  */
  807.     LEFT1F|RIGHT1F  /* Second left and second right channel. */
  808.   };
  809.  
  810.   /* The phonetic string: */  
  811.   char *phonetic_string = "/HEH4LOW";
  812.  
  813.  
  814.   /* Message port opened...    */
  815.   /* "narrator_rb" created...  */
  816.   /* Narrator device opened... */
  817.  
  818.  
  819.   /* Set our requirements: */
  820.  
  821.   /* 1. Give it a pointer to the phonetic string: */
  822.   narrator_req->message.io_Data = (APTR) phonetic_string;
  823.  
  824.   /* 2. Set the length of the phonetic string: */
  825.   narrator_req->message.io_Length = strlen( phonetic_string );
  826.  
  827.   /* 3. Desired channel combinations: */
  828.   narrator_req->ch_masks = allocation_array;
  829.  
  830.   /* 4. Size of the allocation array: */
  831.   narrator_req->nm_masks = sizeof( allocation_array );
  832.  
  833.   /* 5. Send (write) the text to the device: */
  834.   narrator_req->message.io_Command = CMD_WRITE;
  835.  
  836.  
  837. You may of course also change the other values if you do not
  838. want to use the default ones.
  839.  
  840. After the request has been initialized can it be sent to the
  841. narrator device which will read the phonetic string. To send
  842. request you can either use the synchronous command DoIO() or
  843. the asynchronous command SendIO().
  844.  
  845. The DoIO() function will send the request to the device and
  846. put your program to sleep. When the device has finished your
  847. request it is returned and your program wakes up. If something
  848. failed will DoIO() return an error number and a copy of their
  849. value will also be stored in the "io_Error" field of the
  850. request block. 
  851.  
  852. The SendIO() function should be used when you want to continue
  853. to do something while the narrator device is reading the text.
  854. After you have called SendIO() you can put your task to sleep
  855. by either using the WaitIO() or Wait() function. If you want
  856. to check if the request has been completed you can use the
  857. CheckIO() function.
  858.  
  859. All these functions have been described in chapter "Devices",
  860. and will therefore not be repeated here.
  861.  
  862. An example on a synchronous call: (Your program is put to sleep
  863. while the narrator device completes your request.)
  864.  
  865.   BYTE error;
  866.  
  867.   /* ... */
  868.  
  869.   /* Read the text: */
  870.   error = DoIO( narrator_req );
  871.  
  872.   /* Were there any errors? */
  873.   if( error )
  874.     clean_up( "Problems with reading the text!" );
  875.  
  876.  
  877. An example on an asynchronous call: (Your program continues to
  878. run while the text is read.)
  879.  
  880.  
  881.   /* Start to read: */
  882.   SendIO( narrator_req );
  883.  
  884.   while( !CheckIO( narrator_req ) )
  885.   {
  886.     /* Do something... */
  887.   }
  888.  
  889.   /* Collect message at the reply port... */
  890.  
  891.   /* Were there any errors? */
  892.   if( narrator_req->message.io_Error )
  893.     clean_up( "Problems with reading the text!" );
  894.  
  895.  
  896.  
  897. 5.4.4  USING SEVERAL REQUEST BLOCKS
  898.  
  899. If you have created several request blocks will only the one
  900. which you opened the narrator device with be correctly
  901. preinitialized. These structures which have not been initialized
  902. must be prepared before they may be used. The simplest solution
  903. is actually to copy the whole structure, because you will then
  904. be sure that no values are forgotten.
  905.  
  906. Here is an example:
  907.  
  908.   /* Source and destination pointers: */
  909.   BYTE *first_ptr;
  910.   BYTE *second_ptr;
  911.  
  912.  
  913.   /* Allocate request blocks, open narrator device, etc...   */
  914.   /* (The two request blocks are called "first_narrator_req" */
  915.   /* and "second_narrator_req".)                             */
  916.  
  917.   /* Copy the first request block to the second one: */
  918.  
  919.   /* Get the start addresses of both request blocks: */
  920.   first_ptr = (BYTE *) first_narrator_req;
  921.   second_ptr = (BYTE *) second_narrator_req;
  922.  
  923.   /* Copy byte by byte: */
  924.   for( loop = 0; loop < sizeof( struct narrator_rb ); loop++ )
  925.   {
  926.     /* Copy: */
  927.     *second_ptr = *first_ptr;
  928.     
  929.     /* Next byte: */
  930.     first_ptr++;
  931.     second_ptr++;
  932.   }
  933.  
  934.  
  935.  
  936. 5.4.5  CLEAN UP  
  937.  
  938. When your program terminates you have to clean up and free all
  939. allocated resources. This is what has to be done:
  940.  
  941.  1. Remove any messages still left at the message (reply) port.
  942.  
  943.  2. Close the message (reply) port(s).
  944.  
  945.  3. Close the narrator device.
  946.  
  947.  4. Deallocate the request blocks.
  948.  
  949.  
  950.  
  951. 5.4.5.1  REMOVE ALL MESSAGES
  952.  
  953. Before you close anything you should first remove all messages
  954. from the message (reply) port. A short while loop that removes
  955. the messages until it can not find any more is a simple but
  956. effective solution.
  957.  
  958.   while( GetMsg( replymp ) )
  959.     printf( "Collected a message at the reply port.\n" );
  960.  
  961.  
  962.  
  963. 5.4.5.2  CLOSE MESSAGE PORT
  964.  
  965. After all messages have been removed from the port you may close
  966. it by calling the DeletePort() function. Note that you should
  967. never try to close a message port you have not opened.
  968.  
  969.   DeletePort( replymp);
  970.  
  971.  
  972.  
  973. 5.4.5.3  CLOSE THE NARRATOR DEVICE
  974.  
  975. The narrator device itself must of course also be closed if you
  976. have opened it. Note that you should never try to close a
  977. device you have not opened.
  978.  
  979.   CloseDevice( narrator_req );
  980.  
  981.  
  982.  
  983. 5.4.4  DEALLOCATE THE REQUEST BLOCKS
  984.  
  985. Finally you should deallocate all request blocks you have
  986. created. Use the DeleteExtIO() function. The size should be set
  987. to the size of a narrator_rb structure. Just remember to close
  988. the narrator device before you deallocate the request block(s).
  989.  
  990.   DeleteExtIO( narrator_req, sizeof( struct narrator_rb ) );
  991.  
  992.  
  993.  
  994. 5.5  THE NARRATOR'S MOUTH
  995.  
  996. The narrator device offers a rather unique but sometimes useful
  997. feature. The narrator device can be used to draw a mouth as the
  998. text is read. It may sound a bit strange, but if you are using
  999. animations this can be very helpful. 
  1000.  
  1001. The narrator device will tell us how wide and high the mouth
  1002. should be, and with this we can easily construct a simple
  1003. mouth. 
  1004.  
  1005.  
  1006.  
  1007. 5.5.1  MOUTH REQUEST BLOCK
  1008.  
  1009. To use this "mouth" feature you have to use a special request
  1010. block which is called "mouth_rb", and looks like this: (Defined
  1011. in header file "devices/narrator.h".)
  1012.  
  1013. struct mouth_rb
  1014. {
  1015.   struct narrator_rb voice;
  1016.   UBYTE  width;
  1017.   UBYTE  height;
  1018.   UBYTE  shape;
  1019.   UBYTE  pad;
  1020. };
  1021.  
  1022. voice:  The top part of the mouth block consists of a
  1023.         "narrator_rb" structure. When you create this structure
  1024.         the message port will automatically be initialized.
  1025.         The following fields must however be initialized by
  1026.         yourself:
  1027.  
  1028.           1. You must copy the "io_Device" pointer from the
  1029.              request which is reading the text.
  1030.              
  1031.           2. The "io_Unit" number must also be copied.
  1032.  
  1033.           3. The "io_Error" field should be set to zero.
  1034.  
  1035.           4. Finally you should set the command "CMD_READ"
  1036.              in the "io_Command" field.
  1037.  
  1038.         After you have sent this request block and it is
  1039.         returned you can examine the "io_Error" field to
  1040.         check if there were any problems. See above for a
  1041.         complete list of error flags.
  1042.         
  1043.         When you are using this request, it will be returned to
  1044.         you if one of the following thing has happened:
  1045.         
  1046.           1. The size of the mouth has changed.
  1047.         
  1048.           2. Something went wrong, and the "io_Error" field will
  1049.              contain an error flag. If you have received the
  1050.              "ND_NoWrite" the Amiga has stopped talking, and
  1051.              you should not try to draw any mouth any more.
  1052.  
  1053. width:  After you have successfully executed this request you
  1054.         can examine this field to check how wide the mouth
  1055.         should be. The request block will only be returned when
  1056.         the size of the mouth has changed, or the Amiga has
  1057.         stopped talking. 
  1058.  
  1059. height: This field will contain the height of the mouth.
  1060.  
  1061. shape:  This field may only be used by the system, and should
  1062.         never be changed.
  1063.  
  1064. pad:    No used, and should not be used.
  1065.  
  1066.  
  1067.  
  1068. 5.5.2  CREATE A MOUTH REQUEST BLOCK
  1069.  
  1070. Since the size of the mouth_rb is larger than the standard
  1071. sized request block you have to use the CreateExtIO() function
  1072. to allocate and preinitialize the request block. Normally it
  1073. is easiest to connect this structure to the same message port
  1074. as the other request blocks are connected to. You can of course
  1075. use a separate message port if you want.
  1076.  
  1077.   struct mouth_rb *mouth_req;
  1078.  
  1079.   mouth_req = (struct mouth_rb *)
  1080.     CreateExtIO( replymp, sizeof( struct mouth_rb ) );
  1081.  
  1082.   if( !mouth_req )
  1083.     clean_up( "Not enough memory!" );
  1084.  
  1085.  
  1086.  
  1087. 5.5.3  PREPARE THE MOUTH REQUEST BLOCK
  1088.  
  1089. After you have created the mouth_rb structure you have to copy
  1090. some values, as explained above, from the request block which
  1091. will read the text. You must also set some values yourself.
  1092.  
  1093. Here is an example on how to initilaize the mouth request:
  1094.  
  1095.   /* Set the mouth width and height to zero: */
  1096.   mouth_req->width = 0;
  1097.   mouth_req->height = 0;
  1098.  
  1099.   /* Give the mouth request a pointer to the narrator device: */
  1100.   mouth_req->voice.message.io_Device = narrator_req->message.io_Device;
  1101.  
  1102.   /* Give the mouth request the current unit number: */
  1103.   mouth_req->voice.message.io_Unit = narrator_req->message.io_Unit;
  1104.  
  1105.   /* No error number (so far): */
  1106.   mouth_req->voice.message.io_Error = 0;
  1107.  
  1108.   /* The mouth request should look at (read) the request */
  1109.   /* which is currently talking:                         */
  1110.   mouth_req->voice.message.io_Command = CMD_READ;
  1111.  
  1112. The mouth_rb request block can now be used.
  1113.  
  1114.  
  1115.  
  1116. 5.5.4  GET THE SIZE OF THE MOUTH
  1117.  
  1118. The mouth request block should be sent to the narrator device
  1119. after you have sent a normal read request. If the device is
  1120. currently not reading any text the mouth request will
  1121. immediately be returned with the error flag "ND_NoWrite" set.
  1122.  
  1123. If the device is reading some text the mouth request will first
  1124. be returned when the mouth has changed size, or if the narrator
  1125. device has reached the end of the text string. If the device
  1126. reached the end of the string and stops talking the mouth
  1127. request will be returned with the error flag "ND_NoWrite" set.
  1128. However, if the request is returned and no error flag is set,
  1129. the mouth has changed size and should be redrawn.
  1130.  
  1131. Since your program must be able to work while the narrator
  1132. device is reading the text you have to use the asynchronous
  1133. command SendIO() to start the read request. Here is an example
  1134. on how to use the narrator's mouth:
  1135.  
  1136.  
  1137.   /* TRUE as long the Amiga is reading text: */
  1138.   BOOL still_talking;
  1139.  
  1140.   /* ... */
  1141.  
  1142.   /* Start to read: (The read request must be sent by */
  1143.   /* the asynchronous command SendIO().)              */
  1144.   SendIO( narrator_req );
  1145.  
  1146.   /* The Amiga is reading the text: */
  1147.   still_talking = TRUE;
  1148.  
  1149.   /* As long as the Amiga is reading the text */
  1150.   /* we stay in the while loop:               */
  1151.   while( still_talking )
  1152.   {
  1153.     /* Send the mouth request to the narrator device. The request */
  1154.     /* will be returned when the mouth width and/or height have   */
  1155.     /* changed, or the device has stopped reading the text:       */ 
  1156.     DoIO( mouth_req );
  1157.     
  1158.     /* Has the device stopped reading the text: */
  1159.     if( mouth_req->voice.message.io_Error == ND_NoWrite )
  1160.       still_talking = FALSE;
  1161.     else
  1162.     {
  1163.       /* No, the device is still reading. The mouth must have */
  1164.       /* changed, so we better redraw it:                     */
  1165.  
  1166.       /* Draw the new mouth... */ 
  1167.     }
  1168.   }
  1169.  
  1170.   /* We know that the Amiga has stopped speaking,  */
  1171.   /* and hence we do not have to wait for the      */
  1172.   /* narrator to finish reading. We should however */
  1173.   /* check if we have successfully read the text:  */
  1174.   if( narrator_req->message.io_Error )
  1175.     clean_up( "Error while reading!" );
  1176.  
  1177.  
  1178.  
  1179. 5.6  EXAMPLES
  1180.  
  1181. Example 1
  1182.   This very simple example demonstrates how to open the
  1183.   translator library, translate a string, and finally close
  1184.   the library before the program terminates.
  1185.  
  1186. Example 2
  1187.   This example demonstrates how you can use a while loop to
  1188.   translate parts of a string until the whole string has been
  1189.   translated.
  1190.  
  1191. Example 3
  1192.   This example demonstrates how to translate a string into a
  1193.   phonetical string which is then read by the narrator device.
  1194.  
  1195. Example 4
  1196.   This example very similar to the previous one, but this time
  1197.   are we using a different voice. By altering the rate, pitch,
  1198.   mode, sex and volume, you can produce very different sounds.
  1199.  
  1200. Example 5
  1201.   This example demonstrates how you can let the Amiga read
  1202.   small stories. By altering the rate, pitch, mode, sex and
  1203.   volume parameters it can sound like several persons are
  1204.   talking. It can also be used to express emotions and stress
  1205.   important parts of the text.
  1206.  
  1207.   This example is using some home made functions which makes
  1208.   life a little bit easier. If you have to read a lot of text I
  1209.   recommend you to use special functions like these. It will
  1210.   then be much easier to write (and read) the program code.
  1211.  
  1212. Example6
  1213.   This example demonstrates how to use the mouth request block
  1214.   to draw a talking mouth.
  1215.