*******************************************************************************
*******************************************************************************
*******************************************************************************

*******************************************************************************
*                                                                             *
*                        SPEECH!  Advanced programming notes                  *
*                                                                             *
*                          (c) 1986 Superior Software Ltd.                    *
*                                                                             *
*                           written by:   R.C. Peterson                       *
*                                                                             *
*                                                                             *
*******************************************************************************


  Introduction:
  -------------

  These notes will be useful if you want to use the SPEECH!  routines  in  your
own programs. I recommend that you study the  Amstrad  user  guide  and  become
familiar with Basic programming , the AMSDOS memory map and the use of resident
system extensions before attempting to  customise  the  program.  An  essential
document for anyone interested in  machine  code  programming  is  the  Amstrad
Firmware Specification manual ( SOFT 158 ).

  One of the first tasks you should undertake before attempting any alterations
to the SPEECH! programs is to make a working copy of the files we supply (  for
your own use only ! ). Never make alterations to your original disc or cassette
as it is possible to make mistakes if you do not fully understand what is going
on. Feel free to look at the demonstration programs and adapt them for your own
purposes.


  Differences between Locomotive Basic V1.0 and V1.1
  --------------------------------------------------

  The CPC 464 computer is supplied with the Locomotive Basic  interpreter  V1.0
while the CPC 664 and CPC 6128 computers have Locomotive Basic V1.1. As far  as
is known all Basic programs written for V1.0 will run without alteration  under
V1.1. The reverse is not  however  true.  This  only  effects  SPEECH!  in  the
following way: V1.1 allows the programmer to use strings directly in  calls  to
resident system extensions ( RSXs ).

  E.g.

       V1.0 -    100 a$=I think therefore I am
                 110 —SAY,àa$


       V1.1 -    100 —SAY,I think therefore I am


  If you are writing programs which need to run under both Basic V1.0 and  V1.1
then you must use the V1.0 form of the RSX Commands.


  Converting a cassette version of SPEECH! to load from disc.
  -----------------------------------------------------------

  SPEECH! as supplied on cassette is configured to load and save files  to  and
from cassette tape. If you wish to convert a cassette version to  work  with  a
disc system then the following notes may be of help.  Only  minor  changes  are
required to make SPEECH! load from disc. After copying the programs  and  files
to disc you will need to make the following changes:


     Change line 90 in SPEECH.BAS to read:

         90 —DISC

     Change line 60 in EDIT.BAS to read:

         60 —DISC

     Change line 55 in NOTES.BAS to read:

         55 —DISC


  Similarly disc versions of the programs can be converted to operate from tape
using the —TAPE command in place of the the —DISC commands.


  Creating a version of SPEECH! to run at a fixed address.
  --------------------------------------------------------

  The standard SPEECH! program loads into memory at the  top  of  the  block  of
memory reserved for the Basic system. The program requires 7880 bytes of  memory
and so the system variable HIMEM  is  reduced  by  this  amount  and  the  space
available for Basic programs is reduced by the same amount. However the position
of HIMEM is not fixed and depends on whether any resident  system  extensions  (
RSX's ) have been loaded before SPEECH! This means  that  the  program  must  be
relocated so that it will run correctly at whatever address it is  loaded.  This
is done by the loader program SPEECH.BAS.

  The SPEECH! program is stored in two files SPCODE.BIN and SPDICN.BIN. It has a
number of sections. SPDICN.BIN is the dictionary file used in converting English
language text into a phonetic form. This file can be edited using the dictionary
editor EDIT.BAS ( see later ). The file SPCODE.BIN consists of  three  sections.
These are 1) The English text to  phonetics  translator  2)  The  RSX  operating
system interface and 3) The phoneme pronouncer. This last routine  can  be  used
independently from either Basic or machine code programs.

  The easiest way of incorporating the SPEECH!  routines  into  a  machine  code
program is to make a copy of  the  routine  which  has  been  relocated  to  the
required address. To do this you must make the following  temporary  changes  to
the SPEECH program.

     1) Initialise the machine so that no RSX routines are loaded and the
        maximium amount of  memory  is  free. Do  this  by  pressing  the
        <escape> , <shift> and <control> keys simultaneously.

     2) Load the SPEECH! loader program ( SPEECH.BAS ) .

     3) Choose the address at which you would like the  routine  to  load
        and run at.

     4) Set the variable relad in line 102 to the desired  load  address.

     5) replace line 220 with the following line:   220 STOP

     6) Now type RUN.  SPEECH!  will  now  be  loaded  and  the  routines
        relocated. The program will now stop and print the Break message.

     7) Now save the block of code you want using the SAVE command.

         E.g.  SAVE NSPCOD.BIN,B,loadad,len

        The value of loadad will  normally  be  34740 .  To  save  the  whole
        routine len should be 7880 though  this  will  be  different  if  you
        have made any changes  to  the  dictionary. To save  only  the  SPEAK
        routine len should be 4493. If  you  have  made  any  changes  to the
        dictionary then then the value of len will be given by the expression
        lentab + length ( where lentab and length are variables in SPEECH ) .

  You should now have a file on disc or cassette  which  can  be  loaded  back
into  the  machine  at  a  fixed  address  and called  from  either  Basic  or
machine  code.  If  you  are  loading  the  full  routine  you  will  need  to
introduce it to the AMSDOS operating  system  by  CALLing  the  routine  at an
address = loadad + 4493  ( where  loadad  is  the  routines  load  address ) .
Here is a simple loader for a file that  has  been  relocated to load at 32000.

       10 start=32000: length= 7880: init = start + 4493
       20 MEMORY start-1
       30 LOAD NSPCOD.BIN,start
       40 CALL init  ' initialise the routine
       50 —SAY, SPEECH! has now loaded
           .
           .
           .
     9999 END


  Using the SPEAK routine on its own.
  -----------------------------------

  If only the SPEAK routine is loaded then there is no need to  initialise  it.
The SPEAK routine on its own cannot be called  using  the  RSX  commands  —SAY,
—PITCH, —SPEAK etc. To use the SPEAK routine alone it is necessary for the main
program to poke the required phonemes into an area of memory at  the  start  of
the routine. This area occupies the first 255 bytes  of  SPEECH!  The  phonemes
must be stored as upper case letters and digits  and  must  be  followed  by  a
newline character  chr$(13).  The  routine is called at  address  start  +  256
( where start is the address of the routine ).


     100 ' a mini version of SPEECH! has been loaded at address start
     110 phonemes$ = /HEHLLOW5 IY AE2M AY KOOMPUWTER
     130 FOR i = 1 TO LEN(phonemes$)
     140 POKE i+start-1,ASC(MID$(phonemes$,i,1))
     150 NEXT i
     160 POKE i+start,13
     170 CALL start + 256
      .
      .
      .


  Calling SPEECH! from machine code programs.
  -------------------------------------------

  In this section the address start is the load address of the SPEECH! routine.
The pitch  of  the sounds can be altered by poking a  number  corresponding  to
the required pitch into the location start + 285 . This  number must be between
3 and 255 , 3 being the highest pitch, 255 being a very low pitch.

  The sound channel through which SPEECH! operates  can  be  altered  from  its
initial value i.e. through both  channels,  by  poking  one  of  the  following
values into the location start + 301 .

          8  - sound through left channel only.
          9  - sound through both channels.
         10  - sound through right channel only.

  If a copy of the full routine has been loaded and initialised then the  full
set of SPEECH! commands will be available from Basic. These  commands  can  be
called from machine code programs using a program similar to the following:

       SAYCOM EQU start + 4725  ; define the start of the command
       DESCRP DEFS 3            ; reserve space for string descriptor
       STRPOS DEFM /HEHLLOW   ; the string to pronounce
       STRLEN EQU 8             ; the length of the string
       PARLST DEFW 0            ; space for a parameter list


       SPCALL LD HL,DESCRP      ; pointer to string descriptor
              LD A,STRLEN       ; length of string to be passed
              LD (HL),A         ;
              LD BC,STRPOS      ; get start of string
              INC HL            ;
              LD (HL),C         ; save address
              INC HL            ;
              LD (HL),B         ;
              LD HL,DESCRP      ; get address of descriptor
              LD IX,PARLST      ; pointer to parameter list
              LD (IX+0),L       ;
              LD (IX+1),H       ;
              LD A,1            ; only one parameter to be passed
              CALL SAYCOM       ; call the SAY routine
               .
               .
               .

  The SPEAK routine can similarly be called using an identical routine  to  the
one above except calling the routine at an the  address SPKCOM = start + 4684 .
The  pitch   and   channel   can   be   set   using   the   appropriate  POKEs.
It should be noted that the AF BC DE HL registers  are  not  preserved  by  the
SPEECH! routines and should be saved by the  user's  program.  It  should  also
be noted that all interrupts are disabled during  the  routine  which  actually
produces the sounds. The SPEECH! routine requires  complete  control  over  the
sound chip and as a result any sounds  in  the  sound  queue  or  being  played
when the SPEECH! routines are called  will  be  disrupted. If the sound chip is
being used when SPEECH! is called then the sound  queue  should  be flushed and
the sound chip reset otherwise the state  of the  sound  queue  and  sound chip
will be indeterminate. The sound queues  can  be  flushed  from Basic using the
following line:

     SOUND 129,0 : SOUND 130,0 : SOUND 132,0

  From machine code this can be achieved by the following call to the ROM:

     CALL &BCA7    ; reset sound manager and clear all sound queues.

  An alternative way of flushing the sound queues is by printing  the  the  BEL
character CHR$(7) to the screen, this produces a beep sound.


  The SPEECH! memory map.
  -----------------------

           —             —
           —-------------— - start + 7880 = old HIMEM position
           —             —
           — SPDICN.BIN  —
           —             —
           —-------------— - start + 5442
           —             —
           —    text     —
           — translator  —
           —             —
           —-------------—
           —             —
           —     RSX     —
           —  interface  —
           —             —
           —-------------— - start + 4493 = initial entry point
           —             —
           —   Phoneme   —
           —   producer  —
           —             —
           —-------------— - start = New HIMEM position + 1
           —             —
           —   Basic     —
           —   System    —
           —             —


  Editing the SPEECH! dictionary.
  --------------------------------

  The pronunciation of the English language has far too many exceptions for  all
of them to be present in the SPEECH! dictionary. In order to allow you to modify
the dictionary I have included the program EDIT which can  be  called  from  the
main menu. EDIT is designed for editing the SPEECH! dictionary. EDIT allows  you
to play around with the dictionary adding new words and deleting ones you do not
require. The program is a simple line-based editor written in Basic. The program
has not been written to be foolproof but should trap most common errors.

  Ideally you will have access to a floppy disc  system   for  the  storage  of
the data and program files. The cassette  version  is  supplied  so that it can
be used with  cassette  files. Details  of  how  to  convert a cassette version
to run from disc  are  included  in  the section of this help file dealing with
converting SPEECH! for use with discs/cassettes.

  To use the editor first load SPEECH! by typing RUN SPEECH. When SPEECH!  has
loaded type RUN EDIT to load the editor. On loading, the program will ask  you
for the name of a dictionary file. For your first experiments you  can  use  the
basic dictionary we supply. The dictionary  file  will  now  be  loaded  in  and
scanned through. This takes about thirty seconds. Once the file has been  loaded
you are now in command mode and can add, delete or change  any  entry.  Whenever
the editor is in command mode it will display a prompt (  >  ) at which  point
you can type a command.
 All commands are entered as a single character followed by an optional  string
or number. One particularly useful command is the Help command, type the letter
H followed by the return key when in command mode. This will give you a list of
all the commands available.


  The format of the dictionary.
  -----------------------------

  When a line of English text is presented to  the  —SAY  command  it  must  be
translated into a phonetic form before  it  can  be  pronounced.  This  process
is carried out by  a  sub-routine  referred  to  here  as  the  translator. The
translator scans through  its  input-buffer  and  produces  a  list  of phoneme
codes in the output-buffer.

  In order to edit the dictionary successfully it is  important  to  understand
the format of each entry or line. Each line is laid out as follows:

     ‡input-text=output-text‡

  The ‡ characters at the the start and end of the lines must always be present
whenever a dictionary file is saved. The = sign separates  the  two  substrings
which comprise the dictionary entry. The general rule is that if the input-text
is found in the input-buffer then the output-text is sent to the output-buffer.
Thus the input-text always corresponds to a string of normal English characters
and the output-text  is  always comprised of  a  list of phoneme codes. Entries
in the table are stored in groups according to their first character. There are
twenty-eight groups  in  the  dictionary;  for  the  letters  A-Z,  for  space,
and finally one for  other  miscellaneous  characters.The entries in each group
are ordered but not in an obvious way. The translator tries to match the buffer
contents  with  all  the  entries  in  a  group  starting from  the  first  and
choosing the first which provides  a  match.  The relevant number of characters
in the  input-buffer  are  then  skipped  over  and  the  process  is  repeated
until the end of the input-buffer is reached.

  Two characters are treated in a non-standard way by the translator. They  are
the space  character  and  the # ( hash ) character. The hash character can  be
used in the input-text  of  a  dictionary  entry  to indicate a match with  any
character. If a hash character is  found  then  the  input-buffer character  it
matches is stored away. If the match  is  successful then the  stored character
can  be  used  to  take  the  place of another hash character supplied  in  the
output-text.

 If the first character of the input-text is a space then the entry  will match
with the  start  of  a  word.  An  input-text  string   with  a  space  at  the
end will match with the  end  of  a  word.  An  input-text  with   spaces  both
at the start and at the end will only be matched by a whole  word. In  order to
allow for other punctuation marks other than spaces  at  the  end  of words the
translator  will   automatically   match   a   space  in  the  input-text  with
any character other than those in the range 0-9 and A-Z.

  In order to translate correctly English sentences  in  which  the  words  are
separated by single spaces , the translator will  match  a  single  space  with
both the trailing space of the previous word  and  the  leading  space  of  the
following word. As a result when a dictionary  entry  matches  for a whole word
or the end of a word you  should  not  include  a  space  at  the  end  of  the
output-text.

  If this seems complicated you  can  examine  the  standard  dictionary  which
contains many examples. It is  advisable not to make any changes  to  the  main
body of the dictionary as a single change could have complicated  side-effects.
The easiest ways to modify the  dictionary  are 1)  by  adding  whole words and
2) by adding special characters.

    Adding a new word to the dictionary.
   -------------------------------------

    1) First load and run EDIT as explained above.

    2) Load in the dictionary you wish to work with.

    3) First of all you want to find the words section.

        Type:  >F‡<space><return>

    4) You will now see the following line displayed:

        ‡ DAVID = DAYVIHD‡

    5) Now to insert a new entry ( at the start of the words section ).

        Type: >I
              new line :‡ TOMB = TUWM‡
              ‡ TOMB = TUWM‡
              >

    6) step 5) can now be repeated and more words added.

    7) When all the words have been added use the S command to exit and save
       the new version of the dictionary.


   Adding a special character to the dictionary.
   ---------------------------------------------

  The procedure for adding a new character is  almost  identical  to  that  for
adding a new word. First you  need  to  find  the  special  character  section.
You can do this using the following:

        >F‡#
        ‡#‡#‡
        >

  Now you can add a special  character. Any  Ascii  character can be added with
the  exception  of  the   following:    ‡   and   =   and   #   (   hash   )  .
For example you might wish to alter the  %  ( percent )  sign  so  that  it  is
converted into the string of phonemes PERSEHNT . This  can  be  done  with  the
following line:

       >I
       new line: ‡%‡ PERSEHNT ‡
       ‡%‡ PERSEHNT ‡
       >

   This can be repeated until all the characters have been  entered.  Then  the
S command can be used to exit and save the dictionary.



    Saving the dictionary.
    ----------------------

  The dictionary can be saved using the  S  command. It  is  important  not  to
overwrite your copy of the standard dictionary  with  an  experimental version.
If you are experimenting with changes to the dictionary it is advisable to make
a working copy of the software and to use it. If the dictionary gets too  badly
corrupted it may become impossible for the editor to reload it. So  never  make
changes to the disc or cassette we supply.

  The s command takes around thirty seconds to pack the data ready to  save  it.
When this is done a filename is requested and the dictionary  is  saved  out  to
either disc or tape. When this has been done the length of the  new  version  of
the dictionary is  displayed.  This  length  should  be  noted  as  it  must  be
incorporated in the Basic loader program ( SPEECH.BAS ) .

  In order to use the new dictionary a small number of changes must be  made  to
the loader program SPEECH. These are as follows:

     1) Change the filename in line 130 to that of the new dictionary file.

     2) Change to value of length in line 60 to the new dictionary length.

     3) save the program with a new name.

  You now have a customised version of the SPEECH! loader  program  which  will
load SPEECH! together with your  new  dictionary.  It  is  possible  to  add  a
large number of extra words to  the  dictionary.  Each new word will reduce the
space available to other programs and will slow  down  the  translator  program
slightly. It is up to  you to  decide  which  words  you  will  need  for  each
application.

 The editor will allow you to add as many entries to the dictionary as you like,
subject to two constraints: The maximum  number  of  entries  is  given  by  the
variable tpmax in line 110, ( in EDIT ) and the entries when packed together  to
make up the stored dictionary must  not  excede  maxl  bytes  where  maxl  is  a
variable defined in line 105 ( in EDIT ). You can experiment with these  values,
increasing them to use up as much memory as you wish. One possible problem which
should be noted is that the SPEECH! routine must  never  be  so  long  that  the
loader must reduce the top of the Basic system ( HIMEM ) below 16384 as this can
lead to conflicts with the lower ROM.



    EDIT command summary.
    ---------------------

  All commands begin with a single character  which  may  be  either  upper  or
lower case. Some commands have parameters  following  the  letter  -  either  a
number or a string. Other commands give special prompts when data is required.


   H -  The H or Help command will display a brief summary of all the commands.

   X -  The X or eXit command allows the  user  to  leave  the  editor  quickly
        without saving the dictionary file. It  is  possible  to  re-enter  the
        editor using  GOTO 1040 from Basic if the program has not been altered.

   S - The S or Save command will save the  current  dictionary  file to either
       disc or cassette tape. The  user  is  prompted  for  a  filename. If the
       file has been saved successfully  the  length  of  the file in bytes and
       the number of entries will be printed. The length must  be  noted  if it
       is intended to use the dictionary with the standard loader program.


  The following commands all refer to the current edit  line  i.e.  the  user's
present position in the dictionary.


  T - The T or Top command  moves  the  current  edit  line to the start of the
      dictionary.

  B - The B or Bottom command moves the curent edit line  to  the  end  of  the
      dictionary.

  U - The U or Up command allows the user to move  the  current  edit  line  up
      a  single   line.  If  an  optional  number  is  included  after  the  U,
      then the command line will move up by the  specified  number  of lines or
      if this is impossible then to the top of the file.

  D - The D or Down command allows the user  to  move  the  current  edit  line
      down a single line. If  an  optional  number  is  included  after  the  D
      then the current edit  line  will  be  moved down by the specified number
      of lines or if this is impossible then to the end of the file.

  L - The L or List command will list the current line. If it is followed by an
      optional  number then it  will  list the specified number  of  dictionary
      lines from  the  current  position  or  to the end of the file. Note that
      the current edit position is not changed by this command.

  I - The I or Insert command will  insert  a new line into the dictionary. The
      new line is always inserted before the current edit  line.  The  inserted
      line becomes the new edit line. To use the command just enter I and press
      <return> ;  the editor will prompt you for the line to insert.

  K - The K or Kill command will delete the current edit line.

  E - The E or Edit command allows you to edit  the  present  edit  line.  Type
      E followed by <return>. The editor  will  now  ask  for  two  strings  of
      characters. An attempt is made  to  find  the first string in the present
      line and if it is present it is deleted  and  replaced  with  the  second
      string. If the first string is not present  in  the  line  then no change
      is made.

  P - The P or Pronounce command enables you to hear the  phoneme  part  of  an
      entry that you have entered. If the  SPEECH!  RSX  has  not  been  loaded
      before EDIT is run then this command will not work as Basic will
      not recognise the commands. If  you  attempt  to  use  the  P command and
      this causes the editor  to  crash  then  you  can  re-enter  the  program
      from Basic using GOTO 1040.  This  command  can  also get confused if you
      use it on a line which is not correctly formatted.

  F - The F or Find command  enables  you  to  search  through  the  dictionary
      from the current line for  the  string  of  characters  which follows the
      F. e.g. F<space>GIVE<space><return> will search for the  next  occurrence
      of the word give. If the string is not present then you  will find that
      the current edit line is now the last line of  the  file. The   ‡  and  =
      characters which separate the two parts of the line  can   be   used   to
      find entries beginning  or  ending  with  a given  string.  When  a  line
      containing the string is found it becomes the new edit line.



*******************************************************************************
*******************************************************************************
*******************************************************************************