Amiga.org
Operating System Specific Discussions => Amiga OS => Amiga OS -- Development => Topic started by: jjans on September 26, 2004, 07:49:54 PM
-
I am following an old C manual example (Inside the Amiga with C by Thomas Berry published by SAMS) that is dated back to the Lattice days), and Workbench 1.3 in regards to creating a program that makes the Amiga speak using the narrator.device and Translate().
My system is A500, running 3.1 Roms, and I am getting no errors during compile with SASC/C++ 6.xx. I get no crashes when I run the program, and the device seems to open correctly, and the Translate() is returning a converted string to Phonetics OK.
The system is not making any sound however. I was wondering if 2.04 to 3.xx roms handle the speech routines differently than the old 1.3 Roms that I should be aware of?
Is there a modern source example available I could look at to compare with my old example?
/***************************************************/
#include "stdafx.h"
#include "main_protos.h"
struct Library *TranslatorBase=NULL;
extern struct Library *OpenLibrary();
struct MsgPort *WPort, *RPort;
extern struct IORequest *CreateExtIO();
extern struct Library *OpenLibrary();
struct narrator_rb *wmes;
struct mouth_rb *rmes;
BYTE audChanMasks[]={3,5,10,12};
int main(void)
{
UBYTE in_string[80], out_string[300];
printf("Enter a string ");
gets(in_string);
if(get_phoneme(in_string, strlen(in_string),out_string, 300) == ERR)
{
puts("get_phoneme error!");
exit(FALSE);
}
printf("The phoneme translation of %s is %s\n", in_string, out_string);
if(talk_to_me(out_string) == ERR)
exit(FALSE);
return 0;
}
/***************************************************************/
int get_phoneme(in,inLen,out,outLen)
UBYTE *in,*out;
SHORT inLen,outLen;
{
int error=0;
TranslatorBase = (struct Library*)OpenLibrary("translator.library",1);
if(TranslatorBase==NULL)
{
puts("Cannot Open Translator.library!");
return ERR;
}
// Translate this string to phonetics
if(error=Translate(in,inLen,out,outLen) != 0)
{
printf("Cannot Translate %d\n",error);
return ERR;
}
CloseLibrary(TranslatorBase);
return SUCCESS;
}
/***************************************************************/
talk_to_me(speech)
UBYTE *speech;
{
if((WPort=(struct MsgPort*)CreatePort(0,0)) == NULL)
return (ERR);
if((RPort=(struct MsgPort*)CreatePort(0,0)) == NULL)
return (ERR);
if((wmes=(struct narrator_rb*)CreateExtIO(WPort,sizeof(struct
narrator_rb))) == NULL)
return (ERR);
if((rmes=(struct mouth_rb*)CreateExtIO(RPort,sizeof(struct mouth_rb)))
== NULL)
return (ERR);
wmes->message.io_Command = CMD_WRITE;
wmes->message.io_Data = (APTR)speech;
wmes->message.io_Length = strlen(speech);
wmes->ch_masks = audChanMasks;
wmes->nm_masks = sizeof(audChanMasks);
if(OpenDevice("narrator.device", 0, wmes, 0) != 0)
return (ERR);
wmes->mouths = 0;
wmes->volume = 64;
wmes->rate = 20;
wmes->sex = MALE;
wmes->pitch = DEFPITCH;
rmes->voice.message.io_Device = wmes->message.io_Device;
rmes->voice.io_Unit = wmes->message.io_Unit;
rmes->width = 0;
rmes->height = 0;
rmes->voice.message.io_Command = CMD_READ;
rmes->voice.io_Error = 0;
SendIO(wmes);
while(rmes->voice.message.io_Error != ND_NoWrite)
DoIO(rmes);
return(SUCCESS);
}
-
Hi
I thought someone else will reply on this, but it seems like you're doomed with me.
Here is my reply for you: both improved (you asked for it), prepared for SAS/C 6.5x and with the answer for your question inside. Try it and find it out!
Cheers
/***************************************************/
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/translator.h>
#include <clib/alib_protos.h>
#include <dos/dos.h>
#include <devices/narrator.h>
#include <stdio.h>
#include <string.h>
const static BYTE audChanMasks[]={3,5,10,12};
/***************************************************************/
int get_phoneme( UBYTE *in, SHORT inLen, UBYTE *out, SHORT outLen)
{
struct Library *TranslatorBase;
int retVal, error;
TranslatorBase = (struct Library*)OpenLibrary("translator.library",1);
if( !TranslatorBase ) {
puts("Cannot Open Translator.library!");
return RETURN_FAIL;
}
retVal = RETURN_OK;
// Translate this string to phonetics
if(error=Translate(in,inLen,out,outLen) != 0 ) {
printf("Cannot Translate %d\n",error);
retVal = RETURN_FAIL;
}
CloseLibrary(TranslatorBase);
return retVal;
}
/***************************************************************/
int talk_to_me(UBYTE *speech) {
struct narrator_rb *wmes;
struct mouth_rb *rmes;
struct MsgPort *WPort;
struct MsgPort *RPort;
if((WPort=CreatePort(0,0)) == NULL)
return RETURN_FAIL;
if((RPort=CreatePort(0,0)) == NULL ) {
DeletePort( WPort );
return RETURN_FAIL;
}
if((wmes=(struct narrator_rb*)CreateExtIO(WPort,sizeof(struct narrator_rb))) == NULL) {
DeletePort( RPort );
DeletePort( WPort );
return RETURN_FAIL;
}
if((rmes=(struct mouth_rb*)CreateExtIO(RPort,sizeof(struct mouth_rb))) == NULL) {
DeleteExtIO( wmes );
DeletePort( RPort );
DeletePort( WPort );
return RETURN_FAIL;
}
wmes->message.io_Command = CMD_WRITE;
wmes->message.io_Data = (APTR)speech;
wmes->message.io_Length = strlen(speech);
wmes->ch_masks = audChanMasks;
wmes->nm_masks = sizeof(audChanMasks);
if(OpenDevice("narrator.device", 0, wmes, 0) != 0) {
DeleteExtIO( rmes );
DeleteExtIO( wmes );
DeletePort( RPort );
DeletePort( WPort );
return RETURN_FAIL;
}
wmes->mouths = 0;
wmes->volume = 64;
wmes->rate = 20;
wmes->sex = MALE;
wmes->pitch = DEFPITCH;
rmes->voice.message.io_Device = wmes->message.io_Device;
rmes->voice.io_Unit = wmes->message.io_Unit;
rmes->width = 0;
rmes->height = 0;
rmes->voice.message.io_Command = CMD_READ;
rmes->voice.io_Error = 0;
SendIO(wmes);
{
unsigned cnt = 0;
while(rmes->voice.message.io_Error != ND_NoWrite) {
DoIO(rmes);
++cnt;
}
printf( "cnt = %u\n", cnt );
}
WaitPort( WPort );
CloseDevice( wmes );
DeleteExtIO( rmes );
DeleteExtIO( wmes );
DeletePort( RPort );
DeletePort( WPort );
return RETURN_OK;
}
/***************************************************************/
int main(void)
{
UBYTE in_string[] = "test string", out_string[300];
//printf("Enter a string ");
//gets(in_string);
if( get_phoneme(in_string, strlen(in_string),out_string, 300) ) {
puts("get_phoneme error!");
return RETURN_FAIL;
}
printf("The phoneme translation of %s is %s\n", in_string, out_string);
if( talk_to_me(out_string) )
return RETURN_FAIL;
return RETURN_OK;
}
-
Thanks for the example!
Initial compile still gives me no speech, but I have to take some time to study your code to figure out why.
Your Health! :pint: :pint: :pint: :pint:
-
This sounds silly but have you tried using the old AmigaDOS "SAY" command or redirected a text file to SPEAK: to make sure speech is actually make sure it's working??
-
jjans
Oh, so thats wired, as I've tried this and had good expected results, as opposite to your example that didn't work for me.
The reason for this, as I suspect, is the fact that reading 'mouth parameters', DoIO(), is performed only once with failure (I didn't analyse the reason for it), and the whole program exits, before narrator.device even begin to speak, therefore it corrupts memory.
Notice WaitPort() I added to force waiting for narrator.device to finish.
Other changes:
- Cleanup (!!!!!) - Esspecially important in AmigaOS, as this cannot be perfored automatically by OS.
- Usage of other include files that allow to call functions directly from the libraries, without the overhead of so called subs. For that reason I could also change TranslatorBase into local variable.
- Changed function arguments declaration from the old K&R style to the new ANSI style.
- Some functional cleanup (what's the difference between return 0 from main on success end exit( FALSE ) on failure? In my opinion exit() should be avoided at all.
- Used 'const' for really constant array, giving the compiler the possibility to put it in the same hunk with the code itself, not with the data.
Besides this code looks good to me and should work. Try it after rebooting, mayby narrator.device stays corrupted...
Good luck
-
Maybe you don't have narrator.device?
-
Well the AmigaDos 'Say' Command is working on all the machines I tested this on. I tried it on my client machine (also OS 3.1), rebooted to OS 1.3 (via SKICK), and even on WINUAE under different OS configs. Really got me stumped now.
I have a feeling I am missing something really simple here. It may be easier to simply call the exec cli command say (which is working) for my purposes, but then this may be more intense on resources will it not?
I have a feeling that time spent with Visual Studio C++ has spoiled me, and I have to re-read some more basics from the old manuals!:-o
Thanks for your input guys. I'll get it yet!!!!
Gotta go to work now