/* Here is a sample speech demo program that compiles on * Amiga (Lattice) C. It can be thought of as a stripped * down version of the speechtoy (lucas). I haven't * provided the graphics for the drawing of the mouth, * but the access to the mouth variables is shown here. * * It is the sample program from the rev 1.1 ROM KERNEL * manual, now at the printers. * * Rob Peck. * * This code may be freely utilized to create programs for the Amiga. */ #include "exec/types.h" #include "exec/exec.h" #include "exec/nodes.h" #include "exec/lists.h" #include "exec/memory.h" #include "exec/interrupts.h" #include "exec/ports.h" #include "exec/libraries.h" #include "exec/io.h" #include "exec/tasks.h" #include "exec/execbase.h" #include "devices/narrator.h" #include "libraries/translator.h" struct MsgPort *readport=0; struct MsgPort *writeport=0; extern struct MsgPort *CreatePort(); extern struct IORequest *CreateExtIO(); struct narrator_rb *writeNarrator=0; struct mouth_rb *readNarrator=0; struct Library *TranslatorBase=0; UBYTE *sampleinput; /* pointer to sample input string */ UBYTE outputstring[500]; /* place to put the translation */ SHORT rtnCode; /* return code from function */ SHORT readError; SHORT writeError; SHORT error; BYTE audChanMasks[4] = { 3,5,10,12 }; /* which channels to use */ #define CANT_OPEN_TRANSLATOR -100 #define CANT_OPEN_NARRATOR -200 #define CREATE_PORT_PROBLEMS -300 #define CREATE_IO_PROBLEMS -400 #define CANT_PERFORM_WRITE -500 #define REVISION 1 extern struct Library *OpenLibrary(); main() { TranslatorBase = OpenLibrary("translator.library",REVISION); if(TranslatorBase == NULL) exit (CANT_OPEN_TRANSLATOR); sampleinput = "this is a test"; /* a test string of 14 characters */ rtnCode = Translate(sampleinput,14,outputstring,500); error = rtnCode + 100; if(rtnCode != 0) goto cleanup0; writeport = CreatePort(0,0); if(writeport == NULL) { error=CREATE_PORT_PROBLEMS; goto cleanup1; } readport = CreatePort(0,0); if(readport == NULL) { error=CREATE_PORT_PROBLEMS; goto cleanup2; } writeNarrator = (struct narrator_rb *)CreateExtIO(writeport, sizeof(struct narrator_rb)); if(writeNarrator == NULL) { error=CREATE_IO_PROBLEMS; goto cleanup3; } readNarrator = (struct mouth_rb *)CreateExtIO(readport, sizeof(struct mouth_rb)); if(readNarrator == NULL) { error=CREATE_IO_PROBLEMS; goto cleanup4; } /* SET UP THE PARAMETERS FOR THE WRITE-MESSAGE TO THE NARRATOR DEVICE */ /* show where to find the channel masks */ writeNarrator->ch_masks = (audChanMasks); /* and tell it how many of them there are */ writeNarrator->nm_masks = sizeof(audChanMasks); /* tell it where to find the string to speak */ writeNarrator->message.io_Data = (APTR)outputstring; /* tell it how many characters the translate function returned */ writeNarrator->message.io_Length = strlen(outputstring); /* if nonzero, asks that mouths be calculated during speech */ writeNarrator->mouths = 1; /* tell it this is a write-command */ writeNarrator->message.io_Command = CMD_WRITE; /* Open the device */ error = OpenDevice("narrator.device", 0, writeNarrator, 0); if(error != 0) goto cleanup4; /* SET UP THE PARAMETERS FOR THE READ-MESSAGE TO THE NARRATOR DEVICE */ /* tell narrator for whose speech a mouth is to be generated */ readNarrator->voice.message.io_Device = writeNarrator->message.io_Device; readNarrator->voice.message.io_Unit = writeNarrator->message.io_Unit; readNarrator->width = 0; readNarrator->height = 0; /* initial mouth parameters */ readNarrator->voice.message.io_Command = CMD_READ; /* initial error value */ readNarrator->voice.message.io_Error = 0; /* Send an asynchronous write request to the device */ writeError = SendIO(writeNarrator); if(writeError != NULL) { error=CANT_PERFORM_WRITE; goto cleanup5; } /* return immediately, run tasks concurrently */ /* keep sending reads until it comes back saying "no write in progress" */ while((readError = readNarrator->voice.message.io_Error) != ND_NoWrite) { DoIO(readNarrator); /* put task to sleep waiting for a different * mouth shape or return of the message block * with the error field showing no write in * process */ DrawMouth(readNarrator->width,readNarrator->height); /* user's own unique routine, not provided here */ } Delay(30); rtnCode = Translate("No it is not",13,outputstring,500); writeNarrator->sex = FEMALE; writeNarrator->pitch = MAXPITCH; /* raise pitch from default value */ writeNarrator->message.io_Data = (APTR)outputstring; writeNarrator->message.io_Length = strlen(outputstring); DoIO(writeNarrator); Delay(30); rtnCode = Translate("Please! I am speaking now!",26,outputstring,500); writeNarrator->sex = MALE; writeNarrator->pitch = DEFPITCH; writeNarrator->message.io_Data = (APTR)outputstring; writeNarrator->message.io_Length = strlen(outputstring); DoIO(writeNarrator); Delay(30); rtnCode = Translate( "Well, you are not very interesting, so I am going home!", 55,outputstring,500); writeNarrator->sex = FEMALE; writeNarrator->pitch = MAXPITCH; writeNarrator->message.io_Data = (APTR)outputstring; writeNarrator->message.io_Length = strlen(outputstring); DoIO(writeNarrator); Delay(30); rtnCode = Translate("Bye Bye",7,outputstring,500); writeNarrator->sex = MALE; writeNarrator->pitch = DEFPITCH; writeNarrator->rate = 7; /* slow him down */ writeNarrator->message.io_Data = (APTR)outputstring; writeNarrator->message.io_Length = strlen(outputstring); DoIO(writeNarrator); cleanup5: if(writeNarrator != 0) CloseDevice(writeNarrator); /* terminate access to the device */ /* now return system memory to the memory allocator */ cleanup4: if(readNarrator != 0) DeleteExtIO(readNarrator,sizeof(struct mouth_rb)); cleanup3: if(writeNarrator != 0) DeleteExtIO(writeNarrator,sizeof(struct narrator_rb)); cleanup2: if(readport != 0) DeletePort(readport); cleanup1: if(writeport != 0) DeletePort(writeport); cleanup0: if(TranslatorBase != 0) CloseLibrary(TranslatorBase); /* terminate access to the library */ if(error != 0) exit(error); } /* end of test */ DrawMouth(w,h) SHORT w,h; { return(0); /* dummy routine */ } int strlen(string) char *string; { int i,length; length = -1; for(i=0; i<256; i++) /* 256 characters max length at this time */ { if(*string++ == '\0') { length = i+1; break; }; } return(length); } /*********************************************************************** * * Exec Support Function -- Extended IO Request * ***********************************************************************/ extern APTR AllocMem(); /****** exec_support/CreateExtIO ************************************** * * NAME * CreateExtIO() -- create an Extended IO request * * SYNOPSIS * ioReq = CreateExtIO(ioReplyPort,size); * * FUNCTION * Allocates memory for and initializes a new IO request block * of a user-specified number of bytes. * * INPUTS * ioReplyPort - a pointer to an already initialized * message port to be used for this IO request's reply port. * * RESULT * Returns a pointer to the new block. Pointer is of the type * struct IORequest. * * 0 indicates inability to allocate enough memory for the request block * or not enough signals available. * * EXAMPLE * struct IORequest *myBlock; * if( (myBlock = CreateExtIO(myPort,sizeof(struct IOExtTD)) == NULL) * exit(NO_MEM_OR_SIGNALS); * * example used to allocate space for IOExtTD (trackdisk driver * IO Request block for extended IO operations). * * SEE ALSO * DeleteExtIO * ***********************************************************************/ struct IORequest *CreateExtIO(ioReplyPort,size) struct MsgPort *ioReplyPort; LONG size; { struct IORequest *ioReq; if (ioReplyPort == 0) return ((struct IORequest *) 0); ioReq = (struct IORequest *)AllocMem (size, MEMF_CLEAR | MEMF_PUBLIC); if (ioReq == 0) return ((struct IORequest *) 0); ioReq -> io_Message.mn_Node.ln_Type = NT_MESSAGE; ioReq -> io_Message.mn_Node.ln_Pri = 0; ioReq -> io_Message.mn_ReplyPort = ioReplyPort; ioReq -> io_Message.mn_Length = (size - sizeof(struct Message)); /* new (rap) */ return (ioReq); } /****** exec_support/DeleteExtIO ************************************** * * NAME * DeleteExtIO() - return memory allocated for extended IO request * * SYNOPSIS * DeleteExtIO(ioReq,size); * * FUNCTION * See summary line at NAME. Also frees the signal bit which * had been allocated by the call to CreateExtIO. * * INPUTS * A pointer to the IORequest block whose resources are to be freed. * * RESULT * Frees the memory. Returns (no error conditions shown) * * EXAMPLE * struct IORequest *myBlock; * DeleteExtIO(myBlock,(sizeof(struct IOExtTD))); * * example shows that CreateExtIO had been used to create a trackdisk * (extended) IO Request block. * * SEE ALSO * CreateExtIO * **************************************************************************/ DeleteExtIO(ioExt,size) struct IORequest *ioExt; LONG size; { ioExt -> io_Message.mn_Node.ln_Type = 0xff; ioExt -> io_Device = (struct Device *) -1; ioExt -> io_Unit = (struct Unit *) -1; FreeMem (ioExt, size); }