151 lines
5.6 KiB
Plaintext
151 lines
5.6 KiB
Plaintext
/* Talk V1.0 - by Rob Verver in 1992 */
|
|
/* */
|
|
/* With this shellcommand you can make the narrator say any text using the */
|
|
/* new OS2 features. See the helptemplate for more info. When specifying */
|
|
/* a value which is out of range, the correct range will be displayed. */
|
|
/* */
|
|
/* Possible enhancements: */
|
|
/* Ability to speak phonetic strings */
|
|
/* Input from standard input, for piping */
|
|
/* Preferences file in ascii format, controling all settings */
|
|
/* Escape codes changes values halfway a text */
|
|
|
|
OPT OSVERSION=37
|
|
|
|
MODULE 'Translator', 'devices/narrator', 'dos/dos', 'exec/memory', 'exec/io'
|
|
|
|
CONST AUDIOCHANSIZE=4
|
|
ENUM NONE, ERR_DOS, ERR_MEM, ERR_FILE, ERR_DEVICE, ERR_TRANS, ERR_INVALID
|
|
|
|
OBJECT arglist
|
|
file, rate, pitch, robotic, female, volume, enthusiasm, perturb, f1adj,
|
|
f2adj, f3adj, a1adj, a2adj, a3adj, articulate, centralize, centphon, avbias,
|
|
afbias, priority
|
|
ENDOBJECT
|
|
|
|
DEF template, args: arglist, phonebuf=NIL, rdargs=NIL, file=NIL, msgport=NIL,
|
|
filebuf=NIL, ioreq: PTR TO ndi, audiochan: PTR TO CHAR, valid=TRUE,
|
|
length, phonebufsize
|
|
|
|
PROC main () HANDLE
|
|
audiochan := [3, 5, 10, 12]:CHAR
|
|
|
|
/* parse commandline options */
|
|
args := [NIL, [DEFRATE], [DEFPITCH], 0, 0, [DEFVOL], [DEFF0ENTHUS],
|
|
[DEFF0PERT], [0], [0], [0], [0], [0], [0], [DEFARTIC],
|
|
[DEFCENTRAL], NIL, [0], [0], [25]]: arglist
|
|
template := 'FILE,RATE/K/N,PITCH/K/N,ROBOTIC/S,FEMALE/S,VOLUME/K/N,' +
|
|
'ENTHUSIASM/K/N,PERTURB/K/N,F1ADJ/K/N,F2ADJ/K/N,F3ADJ/K/N,' +
|
|
'A1ADJ/K/N,A2ADJ/K/N,A3ADJ/K/N,ARTICULATE/K/N,CENTRALIZE/K/N,' +
|
|
'CENTPHON/K,AVBIAS/K/N,AFBIAS/K/N,PRIORITY/K/N'
|
|
rdargs := ReadArgs (template, args, NIL)
|
|
IF rdargs=NIL THEN Raise (ERR_DOS)
|
|
|
|
/* open translator library */
|
|
translatorbase := OpenLibrary ('translator.library', 37)
|
|
IF translatorbase=NIL THEN Raise (ERR_TRANS)
|
|
|
|
/* open input file */
|
|
file := Open (args.file, MODE_OLDFILE)
|
|
IF file=NIL THEN Raise (ERR_FILE)
|
|
length := FileLength (args.file) /* !!! ascii, no fh */
|
|
IF length<1 THEN Raise (ERR_FILE)
|
|
|
|
/* allocate input buffer */
|
|
filebuf := AllocVec (length, MEMF_PUBLIC)
|
|
IF filebuf=NIL THEN Raise (ERR_MEM)
|
|
|
|
/* allocate buffer for phonetic strings */
|
|
phonebufsize := Shl (length, 1)
|
|
phonebuf := AllocVec (phonebufsize, MEMF_PUBLIC)
|
|
IF phonebuf=NIL THEN Raise (ERR_MEM)
|
|
|
|
/* open narrator device */
|
|
msgport := CreateMsgPort ()
|
|
IF msgport=NIL THEN Raise (ERR_DEVICE)
|
|
ioreq := CreateIORequest (msgport, SIZEOF ndi)
|
|
IF ioreq=NIL THEN Raise (ERR_DEVICE)
|
|
ioreq.flags := NDF_NEWIORB
|
|
IF OpenDevice ('narrator.device', 0, ioreq, NIL)<>NIL THEN Raise (ERR_DEVICE)
|
|
|
|
/* check values validity */
|
|
checkVal (Long (args.rate), MINRATE, MAXRATE, 'Invalid rate')
|
|
checkVal (Long (args.pitch), MINPITCH, MAXPITCH, 'Invalid pitch')
|
|
checkVal (Long (args.volume), MINVOL, MAXVOL, 'Invalid volume')
|
|
checkVal (Long (args.centralize), MINCENT, MAXCENT, 'Invalid centralization')
|
|
IF valid=FALSE THEN Raise (ERR_INVALID)
|
|
|
|
ioreq.chmasks := audiochan
|
|
ioreq.nummasks := AUDIOCHANSIZE
|
|
|
|
/* init values */
|
|
ioreq.rate := Long (args.rate)
|
|
ioreq.pitch := Long (args.pitch)
|
|
ioreq.volume := Long (args.volume)
|
|
ioreq.f0enthusiasm := Long (args.enthusiasm)
|
|
ioreq.f0perturb := Long (args.perturb)
|
|
ioreq.f1adj := Long (args.f1adj)
|
|
ioreq.f2adj := Long (args.f2adj)
|
|
ioreq.f3adj := Long (args.f3adj)
|
|
ioreq.a1adj := Long (args.a1adj)
|
|
ioreq.a2adj := Long (args.a2adj)
|
|
ioreq.a3adj := Long (args.a3adj)
|
|
ioreq.articulate := Long (args.articulate)
|
|
ioreq.centralize := Long (args.centralize)
|
|
ioreq.centphon := Long (args.centphon)
|
|
ioreq.avbias := Long (args.avbias)
|
|
ioreq.afbias := Long (args.afbias)
|
|
ioreq.priority := Long (args.priority)
|
|
IF args.robotic<>NIL THEN ioreq.mode := ROBOTICF0 ELSE ioreq.mode := MANUALF0
|
|
IF args.female<>NIL THEN ioreq.sex := FEMALE
|
|
|
|
process ()
|
|
|
|
Raise (0)
|
|
EXCEPT
|
|
SELECT exception
|
|
CASE ERR_DOS; PrintFault (IoErr(), 'Error')
|
|
CASE ERR_MEM; PutStr ('Error: not enough memory\n')
|
|
CASE ERR_FILE; PutStr ('Error: couldn\at open file\n')
|
|
CASE ERR_DEVICE; PutStr ('Error: couldn\at open narrator device\n')
|
|
CASE ERR_TRANS; PutStr ('Error: could\at open translator library V37\n')
|
|
CASE ERR_INVALID; PutStr ('Error: wrong parameters\n')
|
|
ENDSELECT
|
|
|
|
IF ioreq<>NIL THEN CloseDevice (ioreq) BUT DeleteIORequest (ioreq)
|
|
IF translatorbase<>NIL THEN CloseLibrary (translatorbase)
|
|
IF rdargs<>NIL THEN FreeArgs (rdargs)
|
|
IF phonebuf<>NIL THEN FreeVec (phonebuf)
|
|
IF filebuf<>NIL THEN FreeVec (filebuf)
|
|
IF file<>NIL THEN Close (file)
|
|
IF msgport<>NIL THEN DeleteMsgPort (msgport)
|
|
IF exception THEN CleanUp (10)
|
|
ENDPROC
|
|
|
|
PROC checkVal (val, min, max, str)
|
|
IF val<min OR (val>max)
|
|
Vprintf ('%s: valid values are between %ld and %ld\n', [str, min, max])
|
|
valid := FALSE
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC process ()
|
|
DEF readlen /* !!!! was equal to globvar */
|
|
|
|
readlen := Read (file, filebuf, length)
|
|
IF readlen<>length THEN Raise (ERR_FILE)
|
|
|
|
Translate (filebuf, length, phonebuf, phonebufsize)
|
|
/* WriteF ('phonetic string:\s\n', phonebuf) */
|
|
speakBuffer (phonebuf, StrLen (phonebuf))
|
|
ENDPROC
|
|
|
|
PROC speakBuffer (buffer, length)
|
|
DEF ior:PTR TO iostd
|
|
ior := ioreq
|
|
ior.command := CMD_WRITE
|
|
ior.data := buffer
|
|
ior.length := length
|
|
DoIO (ioreq)
|
|
ENDPROC
|