--- title: "ZVOICE Part 2" type: "article" slug: "zvoice-part-2" url: "http://localhost/article/zvoice-part-2/" markdown_url: "http://localhost/article/zvoice-part-2.md" published_at: "2022-10-07T12:22:51+00:00" modified_at: "2026-06-21T23:22:57+00:00" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "Listing 4 shows how a text to speech program can be implemented. A text string is scanned one word at a time, with \"spaces\" as separators. If the word is in the vocabulary, then the word is spoken; if not found, phonetic pronunciation of the word, or the phrase \"WORD UNKNOWN” is spoken. New words…" category: - name: "CATS Newsletter" slug: "cats-newsletter" taxonomy: "category" url: "http://localhost/category/periodicals/cats-newsletter/" post_tag: - name: "Full Text" slug: "fulltext" taxonomy: "post_tag" url: "http://localhost/tag/fulltext/" - name: "Hardware project" slug: "hardware-project" taxonomy: "post_tag" url: "http://localhost/tag/hardware-project/" - name: "Speech synthesis" slug: "speech-synthesis" taxonomy: "post_tag" url: "http://localhost/tag/speech-synthesis/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Wilf Rigter" slug: "wilf-rigter" taxonomy: "indiv" url: "http://localhost/indiv/wilf-rigter/" publication_r: id: 35941 title: "CATS Newsletter" type: "periodical" url: "http://localhost/periodical/cats-newsletter/" authors: "Wilf Rigter" volume: "4" issue: "10" issues_articles: - id: 39617 title: "CATS v4 n10" type: "issue" url: "http://localhost/issue/cats-v4-n10/" pages: "6" pubdate: "January 1987" related_articles: - id: 36266 title: "ZVOICE" type: "article" url: "http://localhost/article/zvoice/" archive_link: false --- # ZVOICE Part 2 Listing 4 shows how a text to speech program can be implemented. A text string is scanned one word at a time, with “spaces” as separators. If the word is in the vocabulary, then the word is spoken; if not found, phonetic pronunciation of the word, or the phrase “WORD UNKNOWN” is spoken. New words are easily added by defining them as NUMERIC VARIABLES which are then used as an INDEX into the VOCABULARY. ``` B$=PHONEME DATA FOR "ZVOICE" B=LEN B$ B$(B)=CHRS(CODE B$(B)+128) $S(END TO END+B)=B$ ZVOICE=END END=END+B RETURN ``` A$ is a one dimension array which contains the vocabulary in phoneme format. B$ is a new string of phonemes to be added to the vocabulary with the last phoneme identified by adding 128 (set BIT 7). In this example the text word “ZXVOICE” becomes the name of a numeric variable which is set to END, the pointer to the. end of the vocabulary. END is updated by adding the length of the new word in B$ to END. The advantage of this method is natural sounding speech from text, the disadvantage is memory overhead for the vocabulary. The concept of a new phoneme editor is described here which uses cursors or a joystick to take the tedium out of composing phonetic words. This method would arrange the phonemes and common sound element combinations in a matrix or logical array on the screen. The cursor movement would select an element which is provisionally added to the end of a phoneme string and is tested by voicing the whole string including the new element. If it sounds good, it is added to the string, by pushing N/L (ENTER), and then the next element is selected and tested. Words are built up and when complete are added to the vocabulary. Again the text word can be used as the numeric variable index so that the new phoneme string starts at A$(TEXT). In this way any word can be accessed and spoken with the simple BASIC routine: ``` RAND TEXT RAND USR 16514 ``` These routines are just scratching the surface of a comprehensive speech synthesis package. ## So Stay Tuned For More Next time we connect ZVOICE to the telephone, add some AI and start a French/English dictionary. ### Listing 3 ``` BUFF JR BUFF1; LOAD SP0256 DATA INIT JR INIT1; INIT 8255 IF ANY LADR JR LADR1; FIND LINE ADDR. BUFF1 LD HL,(+16400); TOP OF VAR LD DE,05; SKIP VAR HEADER ADD HL,DE; NOTE BUFF2 INC LD DE,(+16434); ADD OFFSET ADD HL,DE; IN SEED POINTER BUFF2 INC HL; NEXT DATA SBY1 IN A,27; TEST BIT 7 BUSY BIT 7,A; BEFORE DATA LOAD JR Z SBY1; REPEAT IF BUSY DATA LD A,(HL); GET BUFF DATA OUT 17,A; LOAD SP0256 DATA STRB XOR A; A=0 OUT 27,A; STROBE LOW CPL; A=FF OUT 27,A; STROBE HIGH LAST LD A,(HL); GET BUFF DATA BIT 7,A; WAS IT LAST DATA? JR Z BUFF2; IF BIT 7=0 LOOP RET; BYE... INIT1 LD A,98; PORT A,C(4-7) = IN OUT 37,A; PORT B,C(0-3) = OUT LD A,0F; DEFAULT DATA=00 OUT 27,A; STROBE HIGH RET; BYE LADR1 LD HL,(+16434); LINE NUMBER CALL 9D8; IN SEED CONVERTS LD DE,5; TO ADDR OF LINE ADD HL,DE; SKIP HEADER AND LD B,H; KEY WORD AND PASS LD C,L; ADDR IN REG BC RET; BACK TO BASIC ``` ### Listing 4 ``` 1 REM 3 DIM A$(256) 4 GOSUB 1000 5 LET HELLO=END 6 DIM V$(16) 7 LET END=END+LEN B$ 10 REM PHONEMES ARE ASSEMBLED IN B$ AND WHEN COMPLETED WORDS ARE ADDED TO VOCABULARY A$ 15 CLS 20 PRINT "PHONEME VOCABULARY LENGTH=";END 30 PRINT 40 PRINT "INPUT PHONEMES 0 TO 63" 50 PRINT """Q"" COMPLETES PHRASE" 60 PRINT """VOC"" = EXIT TO VOCABULARY" 110 LET B$="" 120 INPUT A 125 IF A=VOC THEN GOTO 310 130 LET B$=B$+CHR$ A 140 PRINT A;","; 150 IF A<>Q THEN GOTO 310 199 REM TEXTINPUT/B$ TO BUFFER 200 PRINT AT 19,0;"ENTER TEXT WORD(S)" 210 INPUT T$ 215 PRINT T$ 217 LET A$(END TO END+LEN B$)=B$ 220 RAND END 230 RAND USR 16516 235 PRINT AT 19,0;"PRESS ""R"" TO REPEAT,""C"" TO CANCEL, N/L TO CONTINUE" 240 INPUT C$ 250 IF C$="R" THEN GOTO 220 260 IF C$="C" THEN GOTO 10 270 LET V$(17-LEN T$ TO )=T$ 280 FOR N=1 TO 16 290 POKE 16586+N,CODE V$(N) 295 NEXT N 300 GOTO 5 310 CLS 320 PRINT "ENTER WORD TO BE VOICED","NONEXISTING OR MISSPELLED WORDS RESULT IN ERROR 2/360","GOTO VOC OR PHON TO RECOVER" 330 INPUT C$ 340 IF C$="PHON" THEN GOTO PHON 350 PRINT AT 0,0;C$ 360 RAND VAL C$ 370 RAND USR 16516 380 GOTO 310 1000 LET END=1 1010 LET Q=128 1020 LET VOC=9998 1030 LET PHON=9999 1060 LET B$="" 2000 RETURN 9998 GOTO 310 9999 GOTO 5 ```