home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / devices / narratordevice / example5.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  13KB  |  524 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE) V3.0      Amiga C Club (ACC) */
  4. /* -------------------------------      ------------------ */
  5. /*                                                         */
  6. /* Book:    ACM Devices                 Amiga C Club       */
  7. /* Chapter: Narrator Device             Tulevagen 22       */
  8. /* File:    Example5.c                  181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-04-26                                       */
  11. /* Version: 1.00                                           */
  12. /*                                                         */
  13. /*   Copyright 1992, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20. /* This example demonstrates how you can let the Amiga read */
  21. /* small stories. By altering the rate, pitch, mode, sex    */
  22. /* and volume parameters it can sound like several persons  */
  23. /* are talking. It can also be used to express emotions     */
  24. /* and stress important parts of the text.                  */
  25. /*                                                          */
  26. /* This example is using some home made functions which     */
  27. /* makes life a little bit easier. If you have to read a    */
  28. /* lot of text I recommend you to use special functions     */
  29. /* like these. It will then be much easier to write (and    */
  30. /* read) the program code.                                  */
  31.  
  32.  
  33.  
  34. /* Declares the datatypes like STRPTR etc: */
  35. #include <exec/types.h>
  36.  
  37. /* We are using the narrator device: */
  38. #include <devices/narrator.h>
  39.  
  40.  
  41.  
  42. /* Size of the phonetic string buffer. Note that our   */
  43. /* "translate_and_say()" function will manage strings  */
  44. /* of any size. However, if the string has to be       */
  45. /* divided into several parts there will be a short    */
  46. /* pause between the parts while the function is       */
  47. /* translating the next part. To avoid this you should */
  48. /* not use a too short phonetical string.              */
  49. #define PHONETIC_BUFFER_SIZE 200
  50.  
  51. /* The audio channels: */
  52.  
  53. /* Values: */
  54. #define LEFT0B   0
  55. #define RIGHT0B  1
  56. #define RIGHT1B  2
  57. #define LEFT1B   3
  58.  
  59. /* Bit fields: */
  60. #define LEFT0F   (1<<LEFT0B)
  61. #define RIGHT0F  (1<<RIGHT0B)
  62. #define RIGHT1F  (1<<RIGHT1B)
  63. #define LEFT1F   (1<<LEFT1B)
  64.  
  65.  
  66.  
  67. /* Pointer to the translator library: */
  68. struct Library *TranslatorBase;
  69.  
  70.  
  71.  
  72. /* Declare a pointer to our reply port: */
  73. struct MsgPort *replymp = NULL;
  74.  
  75. /* Declare a pointer to our narrator request block: */
  76. struct narrator_rb *narrator_req = NULL;
  77.  
  78.  
  79.  
  80. /* Declare our functions: */
  81. void main();
  82. void clean_up( STRPTR text );
  83. void prepare_to_read( void );
  84. void translate_and_say
  85. (
  86.   STRPTR original_string,
  87.   UWORD rate,
  88.   UWORD pitch,
  89.   UWORD mode,
  90.   UWORD sex,
  91.   UWORD volume
  92. );
  93. BYTE say
  94. (
  95.   STRPTR translated_string,
  96.   UWORD rate,
  97.   UWORD pitch,
  98.   UWORD mode,
  99.   UWORD sex,
  100.   UWORD volume
  101. );
  102.  
  103.  
  104.  
  105. void main()
  106. {
  107.   /* Prepare the Amiga to read: (Open the translator */
  108.   /* library and narrator device, create and prepare */
  109.   /* the message port and request block.)            */
  110.   prepare_to_read();
  111.  
  112.  
  113.   
  114.   /* Tell a short story: */
  115.  
  116.   /* The story teller: */
  117.   translate_and_say
  118.   (
  119.     "Mr. Hacker is sitting in his room reading a new C manual.",
  120.     DEFRATE,
  121.     DEFPITCH,
  122.     NATURALF0,
  123.     MALE,
  124.     MAXVOL/2
  125.   );
  126.  
  127.   /* The story teller: */
  128.   translate_and_say
  129.   (
  130.     "His lovely wife enters.",
  131.     DEFRATE,
  132.     DEFPITCH,
  133.     NATURALF0,
  134.     MALE,
  135.     MAXVOL/2
  136.   );
  137.  
  138.   /* The wife: */
  139.   translate_and_say
  140.   (
  141.     "Are you still reading the C manual?",
  142.     DEFRATE,
  143.     DEFPITCH + 100,
  144.     NATURALF0,
  145.     FEMALE,
  146.     MAXVOL/2
  147.   );
  148.  
  149.   /* Mr. Hacker: */
  150.   translate_and_say
  151.   (
  152.     "Yes, it is a very good C Manual, made by the Amiga C Club.",
  153.     DEFRATE - 30,
  154.     DEFPITCH - 30,
  155.     NATURALF0,
  156.     MALE,
  157.     MAXVOL/2
  158.   );
  159.  
  160.   /* The wife: */
  161.   translate_and_say
  162.   (
  163.     "Have you paid the registration fee?",
  164.     DEFRATE,
  165.     DEFPITCH + 100,
  166.     NATURALF0,
  167.     FEMALE,
  168.     MAXVOL/2
  169.   );
  170.  
  171.   /* Mr. Hacker: */
  172.   translate_and_say
  173.   (
  174.     "No, why should I pay for something when I don't have to.",
  175.     DEFRATE - 30,
  176.     DEFPITCH - 30,
  177.     NATURALF0,
  178.     MALE,
  179.     MAXVOL/2
  180.   );
  181.  
  182.   /* The wife: */
  183.   translate_and_say
  184.   (
  185.     "You horrible person!",
  186.     DEFRATE + 40,
  187.     DEFPITCH + 100,
  188.     NATURALF0,
  189.     FEMALE,
  190.     MAXVOL
  191.   );
  192.  
  193.   /* The wife: */
  194.   translate_and_say
  195.   (
  196.     "If you do not pay for it I don't want to be married to you!",
  197.     DEFRATE + 20,
  198.     DEFPITCH + 100,
  199.     NATURALF0,
  200.     FEMALE,
  201.     MAXVOL
  202.   );
  203.  
  204.   /* Mr. Hacker: */
  205.   translate_and_say
  206.   (
  207.     "But why are you so upset about it? You normally don't like to waste money.",
  208.     DEFRATE - 30,
  209.     DEFPITCH - 30,
  210.     NATURALF0,
  211.     MALE,
  212.     MAXVOL/2
  213.   );
  214.  
  215.   /* The wife: */
  216.   translate_and_say
  217.   (
  218.     "Mr. Anders Bjerin has been working for several years with this C manual.",
  219.     DEFRATE,
  220.     DEFPITCH + 100,
  221.     NATURALF0,
  222.     FEMALE,
  223.     MAXVOL/2
  224.   );
  225.  
  226.   /* The wife: */
  227.   translate_and_say
  228.   (
  229.     "He made it for you, and you don't want to repay him! That's bad manners.",
  230.     DEFRATE,
  231.     DEFPITCH + 100,
  232.     NATURALF0,
  233.     FEMALE,
  234.     MAXVOL/2
  235.   );
  236.  
  237.   /* Mr. Hacker: */
  238.   translate_and_say
  239.   (
  240.     "Yes, you are right. I will pay the registration fee.",
  241.     DEFRATE - 30,
  242.     DEFPITCH - 30,
  243.     NATURALF0,
  244.     MALE,
  245.     MAXVOL/2
  246.   );
  247.  
  248.   /* The story teller: */
  249.   translate_and_say
  250.   (
  251.     "From now on, Mr. and Mrs. Hacker were living happily ever after.",
  252.     DEFRATE,
  253.     DEFPITCH,
  254.     NATURALF0,
  255.     MALE,
  256.     MAXVOL/2
  257.   );
  258.  
  259.  
  260.  
  261.   /* Clean up and quit: */
  262.   clean_up( "The End!" );
  263. }
  264.  
  265.  
  266.  
  267. /* Close and return everything that has been */
  268. /* opened and allocated before we quit:      */
  269.  
  270. void clean_up( STRPTR text )
  271. {
  272.   /* If we have a request block and the "io_Device" field  */
  273.   /* is not zero, we know that the device has successfully */
  274.   /* been opened and must now be closed:                   */ 
  275.   if( narrator_req && narrator_req->message.io_Device )
  276.     CloseDevice( narrator_req );
  277.  
  278.   /* Empty the reply port: */
  279.   while( GetMsg( replymp ) )
  280.     printf( "Collected a message at the reply port.\n" );
  281.  
  282.   /* Remove the replyport: */
  283.   if( replymp )
  284.     DeletePort( replymp);
  285.  
  286.   /* Dealocate the narrator request block: */
  287.   if( narrator_req )
  288.     DeleteExtIO( narrator_req, sizeof( struct narrator_rb ) );
  289.  
  290.   /* Close the translator library: */
  291.   if( TranslatorBase )
  292.     CloseLibrary( TranslatorBase );
  293.  
  294.  
  295.  
  296.   /* Print the last message: */
  297.   printf( "%s\n", text );
  298.  
  299.   /* Quit: */
  300.   exit( 0 );
  301. }
  302.  
  303.  
  304.  
  305. /* This function will open the translator library and narrator */
  306. /* device, create and initialize the message port and request  */
  307. /* block.                                                      */
  308.  
  309. void prepare_to_read( void )
  310. {
  311.   /* Store error values here: */
  312.   BYTE error;
  313.  
  314.  
  315.   /* Open the translator library: */
  316.   TranslatorBase = (struct Library *)
  317.     OpenLibrary( "translator.library", 0 );
  318.  
  319.   /* Have we successfully opened the library? */
  320.   if( !TranslatorBase )
  321.     clean_up( "Could not open the translator library!" );
  322.  
  323.  
  324.   /* Get a reply port: (No name, priority 0) */
  325.   replymp = (struct MsgPort *)
  326.     CreatePort( NULL, 0 );
  327.   if( !replymp )
  328.     clean_up( "Could not create the reply port!" );
  329.  
  330.  
  331.  
  332.   /* Allocate and preinitialize a narrator request block: */
  333.   narrator_req = (struct narrator_rb *)
  334.     CreateExtIO( replymp, sizeof( struct narrator_rb ) );
  335.   if( !narrator_req )
  336.     clean_up( "Not enough memory for the narrator request!" );
  337.  
  338.  
  339.   /* Open the Narrator Device: */
  340.   error = OpenDevice( "narrator.device", 0, narrator_req, 0 );
  341.   if( error )
  342.   {
  343.     /* Clear the "io_Device" flag since */
  344.     /* we have not opened the device:   */
  345.     narrator_req->message.io_Device = NULL;
  346.   
  347.     /* Quit: */
  348.     clean_up( "Could not open the Narrator Device!" );
  349.   }
  350.  
  351.   /* The translator library and narrator device have now */
  352.   /* been opened. The Amiga can start to speak.          */
  353. }
  354.  
  355.  
  356.  
  357. /* This function will translate a string and will then */
  358. /* automatically call the function "say()" to read     */
  359. /* translated text. The nice thing with this function  */
  360. /* is that it can handle strings of any size. If the   */
  361. /* translated string can not fit into the phonetical   */
  362. /* string, the original string is divided into smaller */
  363. /* parts.                                              */
  364. /*                                                     */
  365. /* You can alter the sound by chaning the parameters   */
  366. /* rate, pitch, mode, sex and volume.                  */
  367.  
  368. void translate_and_say
  369. (
  370.   STRPTR original_string,
  371.   UWORD rate,
  372.   UWORD pitch,
  373.   UWORD mode,
  374.   UWORD sex,
  375.   UWORD volume
  376. )
  377. {
  378.   /* The phonetic string: */
  379.   char phonetic_string[ PHONETIC_BUFFER_SIZE ];
  380.  
  381.   /* If all characters could be translated and stored */
  382.   /* in the phonetic string this variable will be set */
  383.   /* to zero. On the other hand, if some words could  */
  384.   /* not be translated since they did not fit in the  */
  385.   /* phonetic string this variable will contain a     */
  386.   /* negative value on how many characters actually   */
  387.   /* were translated.                                 */
  388.   int char_translated;
  389.   
  390.   /* This variable contsins the current position */
  391.   /* in the string which is translated:          */
  392.   int current_position;
  393.  
  394.  
  395.  
  396.   /* Print the sentence: */
  397.   printf( "%s\n", original_string );
  398.  
  399.  
  400.  
  401.   /* Start with the first character in the original string: */
  402.   current_position = 0;
  403.   
  404.   /* Translate (parts of) our string into phonetics: */
  405.   char_translated =
  406.     Translate( original_string,
  407.                strlen( original_string ),
  408.                phonetic_string,
  409.                PHONETIC_BUFFER_SIZE );
  410.  
  411.  
  412.   /* Let the Amiga read the translated text: */
  413.   /* (We ignore any error messages.)         */
  414.   say( phonetic_string, rate, pitch, mode, sex, volume );
  415.  
  416.  
  417.  
  418.   /* As long as Translate() does not return zero we stay */
  419.   /* in this while loop and continues to translate the   */
  420.   /* original string into phonetics:                     */
  421.   while( char_translated )
  422.   {
  423.     /* Increase the current position in the original string:  */
  424.     /* (Remember that "char_translated" variable is negative, */
  425.     /* and we must therefore use the "-=" operator and not    */
  426.     /* the "+=" to increase the currrent position.[-- = +])   */
  427.     current_position -= char_translated;
  428.  
  429.     /* Translate the following part our string into phonetics: */
  430.     /* (Note that when we put brackets after a string we we    */
  431.     /* get the character at the specified position, but since  */
  432.     /* we want the address of that position we also have to    */
  433.     /* put the pointer "&" sign infront of the string.)        */
  434.     char_translated =
  435.       Translate( &original_string[ current_position],
  436.                  strlen( &original_string[ current_position] ),
  437.                  phonetic_string,
  438.                  PHONETIC_BUFFER_SIZE );
  439.  
  440.     /* Let the Amiga read the translated text: */
  441.     /* (We ignore any error messages.)         */
  442.     say( phonetic_string, rate, pitch, mode, sex, volume );
  443.   }
  444. }
  445.  
  446.  
  447.  
  448. /* This function is given an already translated string */
  449. /* which it will read.                                 */
  450.  
  451. BYTE say
  452. (
  453.   STRPTR translated_string,
  454.   UWORD rate,
  455.   UWORD pitch,
  456.   UWORD mode,
  457.   UWORD sex,
  458.   UWORD volume
  459. )
  460. {
  461.   /* The text should be read with any available channel: */
  462.   UBYTE allocation_array[]=
  463.   {
  464.     LEFT0F,
  465.     RIGHT0F,
  466.     RIGHT1F,
  467.     LEFT1F
  468.   };
  469.  
  470.   /* Store error values here: */
  471.   BYTE error = 0;
  472.  
  473.  
  474.  
  475.   /* Set our requirements: */
  476.  
  477.   /* Set the length of the translated string: */
  478.   narrator_req->message.io_Length = strlen( translated_string );
  479.  
  480.   /* Give it a pointer to the translated string: */
  481.   narrator_req->message.io_Data = (APTR) translated_string;
  482.  
  483.   /* Send (write) the text to the device: */
  484.   narrator_req->message.io_Command = CMD_WRITE;
  485.  
  486.   /* Desired channel combinations: */
  487.   narrator_req->ch_masks = allocation_array;
  488.  
  489.   /* Size of the allocation array: */
  490.   narrator_req->nm_masks = sizeof( allocation_array );
  491.  
  492.   /* Set rate: */
  493.   narrator_req->rate = rate;
  494.  
  495.   /* Set pitch: */
  496.   narrator_req->pitch = pitch;
  497.  
  498.   /* Set mode: */
  499.   narrator_req->mode = mode;
  500.   
  501.   /* Set sex: */
  502.   narrator_req->sex = sex;
  503.  
  504.   /* Set volume: */
  505.   narrator_req->volume = volume;
  506.  
  507.  
  508.  
  509.   /* Start to read: */
  510.   SendIO( narrator_req );
  511.  
  512.   /* Wait for the narrator to finish reading the text: */
  513.   error = WaitIO( narrator_req );
  514.  
  515.   /* Were there any errors? */
  516.   if( error )
  517.     printf( "Error code: %d\n", narrator_req->message.io_Error );
  518.  
  519.  
  520.  
  521.   /* Return any error values or zero if everything is OK: */
  522.   return( error );
  523. }
  524.