Commodore‎ > ‎C128‎ > ‎

SAM 128

   Introduction  
 
SAM is an acronym for Software Automatic Mouth (err, I always thought it meant "Software Activated Mouth").  SAM 128 is a text-to-speech program for the Commodore 128.  Download the latest (Epsilon) version of SAM 128 (including source code and a D64 disk image with SAM, Reciter, Wedge, and several demos).

Strictly speaking, SAM is a "phoneme-to-speech" converter. A separate (but often used) module called "Reciter" is the 'middle-man'. Reciter turns English text into SAM phonemes (which SAM turns into speech).

Thus the combination of "SAM plus Reciter" is a full (English) text-to-speech converter for your Commodore 128!

Because most people who use SAM also invoke Reciter, the combination (SAM+Reciter) may be assumed when others refer to "SAM" (without qualification).  On this web site, I made an effort to clearly distinguish between SAM (only phonetic) and Reciter (SAM + English conversion).

This section of my site is primarily designed to describe details of SAM/Reciter specific to the Commodore 128.  However, I've included a lot of "low-level" details that also apply to the Commodore 64 and Apple II versions.  It is highly recommended that you also read the original (C64) documentation for SAM.  That covers a lot of practical information in a concise manner.  I cover most of the same information on my site, but I go into a lot of technical details that may result in "information overload" (TMI) for some people.  This section of my website also discusses some omissions from, and gives clarification to, topics found (or sometimes, not found) in the original documentation.


   History   
SAM (+Reciter) was originally released for the Commodore 64 (C64) in 1982. It was also released for the Apple II (not sure which version) around the same time. The main difference (AFAIK) is the Apple computer needed an expansion card (a simple DAC, from my research) to render speech.

Based on the Reciter "Dictionary", I think the software was also released for Atari 8-bit computers (but I haven't found any supporting evidence.)  Anyway... SAM/Reciter was released by "Don't Ask, Inc." which I suspect (I ain't no lawyer) is now the intellectual property of SoftVoice.(www.text2speech.com).

This was truly revolutionary software, in my opinion.  With only about 16K of RAM on an 8-bit computer running at 1MHz, you can transform 'any' English text into speech!  Sure the sound quality is laughable by today's standards, and there are many exceptions in the English language not covered by Reciter's dictionary, but the fact this software does an 'acceptable' job and was available to home consumers (or embedded devices) back in 1982 is just amazing.  (With the C128, you have plenty of room to improve the dictionary, however you would need some type of external 'sound card' if you want to seriously improve the audio quality.)

With the popularity of emulators in the early 2000's, I started program Commodores again.  Mostly ML on the C128, but also some firmware stuff too.  I was hoping that somebody would port SAM to the C128 but it never happened, or at least, I never found it on the web.  So in October of 2015, I began disassembling and documenting the original C64 ML code.  After a short while, I made a quick hack that ran on the C128 but it had several issues.  Mainly it wasted a lot of RAM because it was in the middle of BASIC variables (same location used by the C64 version, but in Bank 1).  I released this 'proof of concept' on October 7, 2015.

In early December of 2015, I wrote an actual assembly-language version.  This allowed me to relocate code and data.  Not just move the full bulk, but rearrange modules such that during actual audio rendering, the needed data and code would not be hidden under the I/O region of memory.  I also corrected a nasty bug with the 'error beep' that only affects PAL users! I released this as the Alpha version on December 19, 2015.  Although SAM has several parameters you can tweak, nothing I did would make SAM sound good when the CPU was running at 2MHz (FAST speed). 

A few days later, while surfing the web looking for additional info to include on this web page, I discovered that Sebastian Macke wrote a C version of SAM!  He used automated tools to disassemble the ML and then convert it to C.  So the code is poorly commented (a lot of it makes no sense, unless you are an experienced assembly programmer).  However I did learn a few things, and it was nice to see some of my ideas were 'verified' by another.  Besides a C port, he also made a version of SAM+Reciter for your web browser!

After further study of my assembly code, I realized there is an 'implied' variable which I made explicit (I call it 'tiBase' for time-base).  I also exposed two more hidden variables (that I already knew about) which I collectively refer to as NOISES.  Now with a simple change to these, SAM/Reciter sounds good at 2MHz.  These new variables also give you more ways to manipulate SAM's speech, even if you only use 1MHz (SLOW speed).  On December 27, 2015, I released this as the Beta version.

In early January 2016, I added experimental support for SuperCPU (still awaiting feedback).  In mid-January 2016, I published the latest version which includes a BASIC wedge: now you can easily make SAM speak from BASIC (without using those obscure SYS calls).  I hope you enjoy it!!

Historical note:Microsoft employees SAM in both their "new-millennium" PC operating systems (Windows 2K/XP/7/8/10), and  several smartphones.


   Starting SAM 128 or Reciter 128
 
This is a simple two (or four) step process.   In summary...
  1. Load the raw ML code (SAM128.BIN or RECITER128.BIN)
  2. Install the code (BANK 1: SYS 60928)
  3. For BASIC users, load the wedge (WEDGE.BIN)
  4. For BASIC users, install the wedge (BANK 1: SYS 16384)
My "SAM 128 Epsilon" download includes a BASIC program "QUICK START" which does all four actions for you, in a very simple way.  It is designed for use right after power-up (or reset), and is the first program on the disk.

A slightly more convoluted example is in the BASIC program "JOKE DEMO" which first checks to see if SAM/Reciter and the Wedge have been installed (it does not load them or call Install if they are already present).  See program lines 10~40.  Feel free to use this code in your own BASIC programs.

Following is an explanation of each step for all you hackers!

The first step (#1) is to load the binary file you want into Bank 1.  For SAM (phonetic text), load SAM128.BIN.  For Reciter (English text), load RECITER128.BIN.  In BASIC, you can use a command like this:

  BLOAD"RECITER128.BIN",B1,U8

Change the final 8 if you are loading from a different device.  Once it is loaded, the next (perhaps final) step (#2) is to call the Install routine at 60928 ($EE00).  In BASIC, you can use:

  BANK 1:SYS 60928

This installs a tiny sub-routine in page 1 of memory (common RAM) needed because the operating system's FAR_CALL routine is broken in multiple ways.  It also (perhaps more importantly) reserves the top of RAM so BASIC variables won't destroy SAM or Reciter!   WARNING: The SYS call will reset all BASIC variables, as if you used BASIC command CLR. The following memory is used (depending if you load SAM or Reciter):
  • SAM 128 uses $D800 ~ $FEFF (this leaves 53K free for BASIC variables)
  • Reciter 128 uses $C000 ~ $FEFF (this leaves 47K free for BASIC variables)
Although SAM/Reciter use the memory listed above while actually speaking, between calls to SAM/Reciter, you may use the memory $F700~$FEFF and $D800~$DBFF for temporary work (all in BANK 1).  If you do use the memory from $D800~$DBFF, then do not attempt to use the ]ERROR or ]PHONES commands... these rely on information in that memory area.

At this point, you can use SAM/Reciter with assembly/ML programs.  If you are programming in assembly, you can skip the last two steps.  For BASIC users, I recommend you execute the final two steps listed below, which install the BASIC wedge.  (Note: at this point, you can use SAM/Reciter from BASIC, but you will be forced to use SYS calls.)

Step three (#3) is to load the BASIC Wedge, with a command like this:

  BLOAD"WEDGE.BIN",B1,U8

Change the final 8 if you are loading from a different device.  Note:  this programs loads into address 16384 ($4000) in BANK 1 and will destroy any BASIC variables in that area.  Although this sounds terrible, it is minor compared to the final step...

Once "wedge" is loaded, the final step (#4) is to install the BASIC Wedge with a command like:

  BANK 1:SYS 16384

This installs another tiny sub-routine in page 1 of memory (common RAM), and more importantly writes a small (about 750 byte = 3/4 K) program block just below the current "top of strings".  In other words, the program block is dynamically relocated.  For example (assuming default memory from machine reset):
  • Wedge + SAM128.BIN uses $D500 ~ $FEFF ($300 more than pure SAM... 52K free for BASIC variables)
  • Wedge + Reciter128.BIN uses $BD00 ~ $FEFF ($300 more than pure Reciter... 46K free for BASIC variables)

Besides copying code to the top of (previously) unused RAM, the "wedge install" also does the following things:

  • Saves current iError vector ($300)
  • Changes iError vector (points to BASIC wedge)
  • Resets all BASIC variables, as if you used CLR (this protects the Wedge from being destroyed by BASIC variables)

After step 4, you can issue commands in BASIC like:

]SAY "HELLO, WORLD!"

The BASIC Wedge lies dormant most of the time (thus not slowing your BASIC program).  When a normal (not SAM/Reciter) program would encounter an error, the wedge jumps into action.  If the "error" happens at the beginning of a statement, then the Wedge will check for SAM/Reciter keywords (like ]SAY, ]KNOBS, or ]PITCH).  If this "error" reveals a SAM/Reciter command, then the wedge will invoke the requested command.  Otherwise, the old/saved iError vector will be executed.

Note this is better than some other wedges (like BASIC 8), which will invoke the "new" command(s) at any random time.  Well, that could be a separate article all to itself...

The most important thing to know is that the SAM/Reciter Wedge, like BASIC 8 and other similar wedges (but unlike my 'precise' BASIC 7.80) requires special coding for IF/THEN/ELSE.  In particular, you must include a colon (:) after a THEN or ELSE statement.  This is due to a bug/feature of the BASIC ROM.  For example:

IF T=0 THEN:]SAY "TEST FAILED":ELSE:]SAY"TEST SUCCESS"

Hopefully you see the colon (:) after THEN and ELSE (and before ]SAY...).  The colon is required for the BASIC wedge.

Final/Important Note:
the sub-routine(s) written to Common RAM is(are) in danger of being over-written by the cassette error list.  For this reason, using a cassette is not recommended with SAM 128 or Reciter 128 (because Common RAM is at premium, there is no truly 'safe' place to write the sub-routine[s]).


   Using SAM/Reciter on the Commodore 128  
See the following pages for details on using SAM 128 or Reciter 128 (in either BASIC or Machine Language):
  • Using Reciter 128 (the easy way -- English)
  • Using SAM 128 (the complex way -- phonemes)
  • Common Routines (adjust global parameters, like KNOBS, NOISES, PITCH, SPEED and TIMEBASE)
  • Phoneme table (all SAM phonemes, sorted by "byte code" -- not needed if you use Reciter)
  • Long Alphabetic (all SAM phonemes, sorted by English letter -- not needed if you use Reciter)
  • Technical (details inner workings of SAM/Reciter -- made for hackers)

   Links   
Project64 documentation of (C64) SAM.
Find out more about SAM+Reciter (C64) on Wikipedia
Sebastian Macke's port of SAM to C and web pages

SAM (64) © Don't Ask, Inc., 1982
SAM 128 © H2Obsession, 2015
Webpage © H2Obsession, 2015, 2016, 2018
Comments