home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************/
- /* */
- /* Amiga C Encyclopedia (ACE) V3.0 Amiga C Club (ACC) */
- /* ------------------------------- ------------------ */
- /* */
- /* Book: ACM Devices Amiga C Club */
- /* Chapter: Narrator Device Tulevagen 22 */
- /* File: Example5.c 181 41 LIDINGO */
- /* Author: Anders Bjerin SWEDEN */
- /* Date: 92-04-26 */
- /* Version: 1.00 */
- /* */
- /* Copyright 1992, Anders Bjerin - Amiga C Club (ACC) */
- /* */
- /* Registered members may use this program freely in their */
- /* own commercial/noncommercial programs/articles. */
- /* */
- /***********************************************************/
-
- /* This example demonstrates how you can let the Amiga read */
- /* small stories. By altering the rate, pitch, mode, sex */
- /* and volume parameters it can sound like several persons */
- /* are talking. It can also be used to express emotions */
- /* and stress important parts of the text. */
- /* */
- /* This example is using some home made functions which */
- /* makes life a little bit easier. If you have to read a */
- /* lot of text I recommend you to use special functions */
- /* like these. It will then be much easier to write (and */
- /* read) the program code. */
-
-
-
- /* Declares the datatypes like STRPTR etc: */
- #include <exec/types.h>
-
- /* We are using the narrator device: */
- #include <devices/narrator.h>
-
-
-
- /* Size of the phonetic string buffer. Note that our */
- /* "translate_and_say()" function will manage strings */
- /* of any size. However, if the string has to be */
- /* divided into several parts there will be a short */
- /* pause between the parts while the function is */
- /* translating the next part. To avoid this you should */
- /* not use a too short phonetical string. */
- #define PHONETIC_BUFFER_SIZE 200
-
- /* The audio channels: */
-
- /* Values: */
- #define LEFT0B 0
- #define RIGHT0B 1
- #define RIGHT1B 2
- #define LEFT1B 3
-
- /* Bit fields: */
- #define LEFT0F (1<<LEFT0B)
- #define RIGHT0F (1<<RIGHT0B)
- #define RIGHT1F (1<<RIGHT1B)
- #define LEFT1F (1<<LEFT1B)
-
-
-
- /* Pointer to the translator library: */
- struct Library *TranslatorBase;
-
-
-
- /* Declare a pointer to our reply port: */
- struct MsgPort *replymp = NULL;
-
- /* Declare a pointer to our narrator request block: */
- struct narrator_rb *narrator_req = NULL;
-
-
-
- /* Declare our functions: */
- void main();
- void clean_up( STRPTR text );
- void prepare_to_read( void );
- void translate_and_say
- (
- STRPTR original_string,
- UWORD rate,
- UWORD pitch,
- UWORD mode,
- UWORD sex,
- UWORD volume
- );
- BYTE say
- (
- STRPTR translated_string,
- UWORD rate,
- UWORD pitch,
- UWORD mode,
- UWORD sex,
- UWORD volume
- );
-
-
-
- void main()
- {
- /* Prepare the Amiga to read: (Open the translator */
- /* library and narrator device, create and prepare */
- /* the message port and request block.) */
- prepare_to_read();
-
-
-
- /* Tell a short story: */
-
- /* The story teller: */
- translate_and_say
- (
- "Mr. Hacker is sitting in his room reading a new C manual.",
- DEFRATE,
- DEFPITCH,
- NATURALF0,
- MALE,
- MAXVOL/2
- );
-
- /* The story teller: */
- translate_and_say
- (
- "His lovely wife enters.",
- DEFRATE,
- DEFPITCH,
- NATURALF0,
- MALE,
- MAXVOL/2
- );
-
- /* The wife: */
- translate_and_say
- (
- "Are you still reading the C manual?",
- DEFRATE,
- DEFPITCH + 100,
- NATURALF0,
- FEMALE,
- MAXVOL/2
- );
-
- /* Mr. Hacker: */
- translate_and_say
- (
- "Yes, it is a very good C Manual, made by the Amiga C Club.",
- DEFRATE - 30,
- DEFPITCH - 30,
- NATURALF0,
- MALE,
- MAXVOL/2
- );
-
- /* The wife: */
- translate_and_say
- (
- "Have you paid the registration fee?",
- DEFRATE,
- DEFPITCH + 100,
- NATURALF0,
- FEMALE,
- MAXVOL/2
- );
-
- /* Mr. Hacker: */
- translate_and_say
- (
- "No, why should I pay for something when I don't have to.",
- DEFRATE - 30,
- DEFPITCH - 30,
- NATURALF0,
- MALE,
- MAXVOL/2
- );
-
- /* The wife: */
- translate_and_say
- (
- "You horrible person!",
- DEFRATE + 40,
- DEFPITCH + 100,
- NATURALF0,
- FEMALE,
- MAXVOL
- );
-
- /* The wife: */
- translate_and_say
- (
- "If you do not pay for it I don't want to be married to you!",
- DEFRATE + 20,
- DEFPITCH + 100,
- NATURALF0,
- FEMALE,
- MAXVOL
- );
-
- /* Mr. Hacker: */
- translate_and_say
- (
- "But why are you so upset about it? You normally don't like to waste money.",
- DEFRATE - 30,
- DEFPITCH - 30,
- NATURALF0,
- MALE,
- MAXVOL/2
- );
-
- /* The wife: */
- translate_and_say
- (
- "Mr. Anders Bjerin has been working for several years with this C manual.",
- DEFRATE,
- DEFPITCH + 100,
- NATURALF0,
- FEMALE,
- MAXVOL/2
- );
-
- /* The wife: */
- translate_and_say
- (
- "He made it for you, and you don't want to repay him! That's bad manners.",
- DEFRATE,
- DEFPITCH + 100,
- NATURALF0,
- FEMALE,
- MAXVOL/2
- );
-
- /* Mr. Hacker: */
- translate_and_say
- (
- "Yes, you are right. I will pay the registration fee.",
- DEFRATE - 30,
- DEFPITCH - 30,
- NATURALF0,
- MALE,
- MAXVOL/2
- );
-
- /* The story teller: */
- translate_and_say
- (
- "From now on, Mr. and Mrs. Hacker were living happily ever after.",
- DEFRATE,
- DEFPITCH,
- NATURALF0,
- MALE,
- MAXVOL/2
- );
-
-
-
- /* Clean up and quit: */
- clean_up( "The End!" );
- }
-
-
-
- /* Close and return everything that has been */
- /* opened and allocated before we quit: */
-
- void clean_up( STRPTR text )
- {
- /* If we have a request block and the "io_Device" field */
- /* is not zero, we know that the device has successfully */
- /* been opened and must now be closed: */
- if( narrator_req && narrator_req->message.io_Device )
- CloseDevice( narrator_req );
-
- /* Empty the reply port: */
- while( GetMsg( replymp ) )
- printf( "Collected a message at the reply port.\n" );
-
- /* Remove the replyport: */
- if( replymp )
- DeletePort( replymp);
-
- /* Dealocate the narrator request block: */
- if( narrator_req )
- DeleteExtIO( narrator_req, sizeof( struct narrator_rb ) );
-
- /* Close the translator library: */
- if( TranslatorBase )
- CloseLibrary( TranslatorBase );
-
-
-
- /* Print the last message: */
- printf( "%s\n", text );
-
- /* Quit: */
- exit( 0 );
- }
-
-
-
- /* This function will open the translator library and narrator */
- /* device, create and initialize the message port and request */
- /* block. */
-
- void prepare_to_read( void )
- {
- /* Store error values here: */
- BYTE error;
-
-
- /* Open the translator library: */
- TranslatorBase = (struct Library *)
- OpenLibrary( "translator.library", 0 );
-
- /* Have we successfully opened the library? */
- if( !TranslatorBase )
- clean_up( "Could not open the translator library!" );
-
-
- /* Get a reply port: (No name, priority 0) */
- replymp = (struct MsgPort *)
- CreatePort( NULL, 0 );
- if( !replymp )
- clean_up( "Could not create the reply port!" );
-
-
-
- /* Allocate and preinitialize a narrator request block: */
- narrator_req = (struct narrator_rb *)
- CreateExtIO( replymp, sizeof( struct narrator_rb ) );
- if( !narrator_req )
- clean_up( "Not enough memory for the narrator request!" );
-
-
- /* Open the Narrator Device: */
- error = OpenDevice( "narrator.device", 0, narrator_req, 0 );
- if( error )
- {
- /* Clear the "io_Device" flag since */
- /* we have not opened the device: */
- narrator_req->message.io_Device = NULL;
-
- /* Quit: */
- clean_up( "Could not open the Narrator Device!" );
- }
-
- /* The translator library and narrator device have now */
- /* been opened. The Amiga can start to speak. */
- }
-
-
-
- /* This function will translate a string and will then */
- /* automatically call the function "say()" to read */
- /* translated text. The nice thing with this function */
- /* is that it can handle strings of any size. If the */
- /* translated string can not fit into the phonetical */
- /* string, the original string is divided into smaller */
- /* parts. */
- /* */
- /* You can alter the sound by chaning the parameters */
- /* rate, pitch, mode, sex and volume. */
-
- void translate_and_say
- (
- STRPTR original_string,
- UWORD rate,
- UWORD pitch,
- UWORD mode,
- UWORD sex,
- UWORD volume
- )
- {
- /* The phonetic string: */
- char phonetic_string[ PHONETIC_BUFFER_SIZE ];
-
- /* If all characters could be translated and stored */
- /* in the phonetic string this variable will be set */
- /* to zero. On the other hand, if some words could */
- /* not be translated since they did not fit in the */
- /* phonetic string this variable will contain a */
- /* negative value on how many characters actually */
- /* were translated. */
- int char_translated;
-
- /* This variable contsins the current position */
- /* in the string which is translated: */
- int current_position;
-
-
-
- /* Print the sentence: */
- printf( "%s\n", original_string );
-
-
-
- /* Start with the first character in the original string: */
- current_position = 0;
-
- /* Translate (parts of) our string into phonetics: */
- char_translated =
- Translate( original_string,
- strlen( original_string ),
- phonetic_string,
- PHONETIC_BUFFER_SIZE );
-
-
- /* Let the Amiga read the translated text: */
- /* (We ignore any error messages.) */
- say( phonetic_string, rate, pitch, mode, sex, volume );
-
-
-
- /* As long as Translate() does not return zero we stay */
- /* in this while loop and continues to translate the */
- /* original string into phonetics: */
- while( char_translated )
- {
- /* Increase the current position in the original string: */
- /* (Remember that "char_translated" variable is negative, */
- /* and we must therefore use the "-=" operator and not */
- /* the "+=" to increase the currrent position.[-- = +]) */
- current_position -= char_translated;
-
- /* Translate the following part our string into phonetics: */
- /* (Note that when we put brackets after a string we we */
- /* get the character at the specified position, but since */
- /* we want the address of that position we also have to */
- /* put the pointer "&" sign infront of the string.) */
- char_translated =
- Translate( &original_string[ current_position],
- strlen( &original_string[ current_position] ),
- phonetic_string,
- PHONETIC_BUFFER_SIZE );
-
- /* Let the Amiga read the translated text: */
- /* (We ignore any error messages.) */
- say( phonetic_string, rate, pitch, mode, sex, volume );
- }
- }
-
-
-
- /* This function is given an already translated string */
- /* which it will read. */
-
- BYTE say
- (
- STRPTR translated_string,
- UWORD rate,
- UWORD pitch,
- UWORD mode,
- UWORD sex,
- UWORD volume
- )
- {
- /* The text should be read with any available channel: */
- UBYTE allocation_array[]=
- {
- LEFT0F,
- RIGHT0F,
- RIGHT1F,
- LEFT1F
- };
-
- /* Store error values here: */
- BYTE error = 0;
-
-
-
- /* Set our requirements: */
-
- /* Set the length of the translated string: */
- narrator_req->message.io_Length = strlen( translated_string );
-
- /* Give it a pointer to the translated string: */
- narrator_req->message.io_Data = (APTR) translated_string;
-
- /* Send (write) the text to the device: */
- narrator_req->message.io_Command = CMD_WRITE;
-
- /* Desired channel combinations: */
- narrator_req->ch_masks = allocation_array;
-
- /* Size of the allocation array: */
- narrator_req->nm_masks = sizeof( allocation_array );
-
- /* Set rate: */
- narrator_req->rate = rate;
-
- /* Set pitch: */
- narrator_req->pitch = pitch;
-
- /* Set mode: */
- narrator_req->mode = mode;
-
- /* Set sex: */
- narrator_req->sex = sex;
-
- /* Set volume: */
- narrator_req->volume = volume;
-
-
-
- /* Start to read: */
- SendIO( narrator_req );
-
- /* Wait for the narrator to finish reading the text: */
- error = WaitIO( narrator_req );
-
- /* Were there any errors? */
- if( error )
- printf( "Error code: %d\n", narrator_req->message.io_Error );
-
-
-
- /* Return any error values or zero if everything is OK: */
- return( error );
- }
-