Commodore‎ > ‎C128‎ > ‎SAM 128‎ > ‎


  Common BASIC Commands for SAM 128 and Reciter 128
Below is the list of commands that may be used with the BASIC Wedge of SAM 128.  They may be used weather SAM or Reciter has been loaded.  (See much later for ML and non-wedge alternatives.)  The common BASIC-Wedge commands are:
  • ]CPUFIX -- adjusts some SAM parameters for your current machine settings (SCPU, NTSC/PAL, FAST/SLOW).
  • ]ERROR -- displays last phoneme translation (and the first error [if any] is shown in reverse font);
            the input text translated from English to SAM phonemes (if using Reciter)
  • ]KNOBS mm, tt -- adjust "Mouth" and "Throat" formants
  • ]LIGHTS boolean -- enable [not zero] / disable [zero] VIC-II display during speech
  • ]NOISES xx, yy -- adjust the PCM sample rate for type X and type Y phones
  • ]PHONES -- displays internal "phones" (as translated from SAM "phonemes")
  • ]PITCH nn -- controls SAM's pitch (regardless of "current CPU") -- Note: higher values yield lower frequency!
  • ]QUIT -- removes SAM/Reciter/Wedge from BASIC (note: deletes all variables!).
  • ]RECITER -- Do English text-to-speech (in following ]SAY commands)
  • ]SAM -- Do phonetic text-to-speech (in following ]SAY commands)
  • ]SAY string -- Speak the word(s) in the string... either phonetic (SAM) or English (Reciter)
  • ]SPEED nn -- controls SAM's rate-of-speech -- Note: higher values yield slower speed!
  • ]TIMEBASE nn -- manual adjustment of F_Sample phase period (part of CPUFIX);
            changes the perceived affects of PITCH and SPEED (which don't really change)

The BASIC-Wedge commands are easy to spot because they all must be entered with a leading close-bracket "]".  The pages discussing SAM and Reciter generally don't include this leading bracket for ease-of-reading (unless an example is given to be entered).  The above list gives a brief description of each, and the next few paragraphs talks about the syntax they use.  More detailed information about these commands can be found in other sections (referenced in the following paragraphs).

Like the original C64 version of SAM, commands may be abbreviated by omitting letters from the end, as long as there is no ambiguity.  For example, you may type ]ERR (or simply ]E) instead of typing out ]ERROR in full.  However, you may not abbreviate ]SAY with ]SA because that might also refer to ]SAM.

Some of the BASIC-Wedge commands use no arguments (CPUFIX, ERROR, PHONES, QUIT, RECITER, SAM).  If you are not using the BASIC Wedge, you will need to SYS a special address which is specific to the desired command (see the section Common ML Routines, below).  Of these, CPUFIX and PHONES are unique to the C128 port of SAM.  Note: if you did not load Reciter 128 (i.e., you loaded SAM128.BIN instead), then ]RECITER will not do anything (silent failure).

Many of the BASIC-Wedge commands take one or two numeric arguments (KNOBS, LIGHTS, NOISES, PITCH, SPEED, TIMEBASE).  For all of them, a non-numeric (string) argument will cause a TYPE MISMATCH ERROR. For all of them, floating-point values will be converted to integers as if the BASIC INT() function had been used.  With one exception (TIMEBASE), the numeric value must be in the range of 0 to 255, or an ILLEGAL QUANTITY ERROR will occur (for TIMEBASE, the value must be in the range 0 to 65535).  A value of 0 is silently ignored in all of these commands, except LIGHTS.  The argument to LIGHTS is Boolean: zero means false (don't show the VIC screen) and any other legal number is true (show the VIC screen).  If you are not using the BASIC Wedge, all of these commands can be accessed with a single SYS address (see the section Poker, below).  Of these, NOISES and TIMEBASE are unique to the C128 port of SAM.

The KNOBS (and NOISES) command may take up to 2 arguments.  You may also omit one of the arguments (in which case, the previous value will remain in effect).  You may not omit both arguments (this will cause a SYNTAX ERROR).  Examples:

]KNOBS , 64 :REM omit first argument

]KNOBS 92  :REM omit second argument

The SAY command is unique in that it is the only BASIC-Wedge command which takes a string argument.  If the argument is missing, SYNTAX ERROR will be generated.  If the argument is numeric (not a string), a TYPE MISMATCH ERROR occurs.  Otherwise, the argument may be any valid BASIC expression (constant, scalar, array, function, or generic string expression).  The string will be interpreted as either phonetic text (for SAM) or English text (for Reciter).  If you loaded Reciter 128, you may switch between phonetic and English evaluation with commands SAM and RECITER, respectively.  If you loaded SAM 128, the argument will always be treated as phonetic text.  Many things will cause an error in phonetic text (see the SAM page for details).  Everything and anything is allowed in English text (see the Reciter page for details).

  BASIC Wedge on the Commodore 128
The BASIC Wedge is a separate module that may be loaded in the C128 port of SAM.  In the C64 version, the wedge was always loaded.  My C128 port makes the wedge optional for several reasons.  First, SAM is easy to use from ML, so it would be wasteful to include the Wedge in a program that doesn't use BASIC.  Second, using separate modules helps maintain a clear separation of functionality ("structured programming"), and should help anyone who wants to study or hack SAM.  Third, the Wedge uses "unsafe" (but normally unused) stack page for cross-bank operations, so SAM will be more stable if you don't use the Wedge.

To use the BASIC Wedge, you first need to install either SAM or Reciter (see the SAM 128 page for details).  Then you load WEDGE.BIN into Bank 1 RAM.  In BASIC you would do something like this:

which loads the file into Bank 1 at address 16384 ($4000).  Next call the install routine at $4000; in BASIC you would write something like:
BANK 1: SYS 16384

The install routine will first look at the current end-of-strings pointer for BASIC.  This will be the start of SAM/Reciter if used just installed that. Then it subtracts the amount of memory it needs to run (or a little more, to ensure page alignment) to get a new (lower) end-of-strings.  The current Wedge uses 768 bytes (0.75 KB).  Next, code is relocated to the new address.  Finally the BASIC pointers are updated to reflect the reduced amount of memory available.  Note: the final step effectively erases all BASIC variables!

Besides being in a separate module, there is one other important difference in the way the BASIC Wedge in the C128 version works (compared to the original C64 version).  The "iError" vector is redirected, instead of replacing the "CharGet" routine.  For ML hackers, this is mainly trivia, but for BASIC users, this change brings some nice benefits, one annoying incompatibility, and one "be careful" ("gotcha") issue.

The benefits of the C128 Wedge (versus C64) are:

  1. Faster speed for BASIC as a whole -- other keywords/constants are not slowed down
  2. You can use any BASIC expression where an argument is needed; examples...
    • Use any of: 123 (a literal number), V (a scalar variable), T(3) (an array variable), FNY(X) (a custom function), or (V+Q)*3-1 (a generic expression).  In comparison, the C64 version only allows a literal number... how restrictive!
    • Use any of "HELLO" (a string literal), V$ (a scalar variable), T$(3) (an array variable), or MID$(Q$,P,2)+"LO" (a generic expression).  In comparison, the C64 version only allows a string literal or a scalar variable.

The one annoying incompatibility is you must use ]SAY in the C128 Wedge.  On the C64, you could simply use SAY.  This is not a big deal when writing new programs, but is annoying when you want to port an existing program.  I considered several ways to get the C64 behavior, but they would either be slow (CharGet replacement) or would require a lot of text re-scanning and other tricks (which is slow to execute and consumes more memory).  I believe the benefits outweigh the cost of "not 100% portable".  Also, because the C64 version doesn't allow variables or expressions for numeric arguments, any SAM program that wants to dynamically change PITCH or SPEED (for example) must rely on POKEs instead, which makes the C64 version "non-portable" to begin with (a priori).

The "gotcha" relates to the power of generic expressions combined with abbreviated commands.  For example, if you wanted to change SAM's rate-of-speech with a variable named D1, you could write:
but if you a tried to abbreviate this like
then it would (generally) fail because it would be interpreted as
(note there is no variable, only a constant!)

The above was an arbitrary example of how things can go wrong.  You can probably imagine many other ways.  So be careful with abbreviations (or better: don't use them).  If something acts weird with abbreviations, this may be the issue.

  Common ML Routines for SAM 128 and Reciter 128
Despite its title, this section (and the remaining sections) may be useful to BASIC programmers who do not want to use the Wedge (or who are just curious).  This section is about commands that are not unique to either SAM or Reciter (i.e., available to both).

For ML programmers, you will find a jump table beginning at $EE00 (the dictionary is only present if you load Reciter):
.EE00 JMP Install   ;clears BASIC variables!
.EE03 JMP Remove    ;clears BASIC variables!
.EE09 JMP SayIt
.EE0C JMP ReSyBASIC ;only if you loaded Reciter 128
.EE0F JMP Reciter   ;only if you loaded Reciter 128
.EE15 JMP DspErr    ;ERROR
.EE18 JMP Peeker
.EE1E JMP CPUfix    ;adjust TIMEBASE and NOISES per CPU speed and NTSC/PAL
.EE21 BIT samStr    ;location of input string/buffer
.EE24 BIT dicAlphaLo ;location of Dictionary index (index A -> start of dictionary)
.EE27 BIT ChrTab    ;location of Dictionary character classification table
.EE2A JSR WrFarCall ;install temporary cross-bank routine in Common RAM
Note that 3 of the last 4 entries (those with a BIT opcode) are not routines which a programmer may call.  Each simply references an important memory location that a programmer might need.  If the dictionary is not present (you loaded SAM instead of Reciter), then the last two BIT entries will refer to address zero.

The Install routine at 60928 ($EE00) might be considered a common routine, depending on how liberal your definitions are!  Conceptually it operates the same for both SAM and Reciter.  In reality, the Reciter version will reserve more memory (leave less BASIC variable space free to use).

One common routine, which is very simple, is the Remove (uninstall) routine at 60931 ($EE03).  This just resets BASIC's variables so that all RAM in Bank 1 (up to $FF00) is available to BASIC.  Warning: if you installed the BASIC-Wedge, be sure to use its ]QUIT command; otherwise, the wedge will remain active, but BASIC variables can start destroying SAM code, which will eventually cause a system crash!

Technically speaking, the two main SAM routines, SayItBASIC at 60934 ($EE06) and SayIt at 60937 ($EE09), are common routines (you can call SAM even if you did not load Reciter 128).  For more details on these, refer to the SAM page.  In contrast, the two main Reciter routines, ReSyBASIC at 60940 ($EE0C) and Reciter at 60943 ($EE0F) are unique (not common).  For details of them, refer to the Reciter page. Note: if you load SAM (instead of Reciter), calling those routines will do nothing (silent failure).

The DspErr routine (ERROR) at 60949 ($EE15) is most useful when using SAM (see the SAM page), but may also be useful with Reciter to see how your English text was converted into phonemes (see the Reciter page).

The DspPhones routine (PHONES) at 60955 ($EE1B) is most useful to the SAM programmer.  It shows how the input phoneme text was "exploded" into sub-phonemes ("phones") along with the application of internal stress rules and phrase breaks.  See the SAM page for details.  Can also be used after loading Reciter, but is mainly a curiosity since you can't specify phonetic text (unless you switch to SAM-Mode).

This common routine, at 60958 ($EE1E), adjusts 3 internal values (NOISES X, NOISES Y, and TIMEBASE) to get the classic (C64/NTSC) voice of SAM, despite hardware differences (NTSC/PAL crystals and CPU speed).

1 MHz
2 MHz
20 MHz
NTSC 7 18 220
PAL 6 17 211

1 MHz
2 MHz
20 MHz
NTSC 6 16 196
PAL 5 15 188

1 MHz
2 MHz
20 MHz
NTSC 2 30 582
PAL 1 28 558

CPUFIX does not make changes to settings that are due to software differences; thus it does not directly modify things like KNOBS, PITCH, and SPEED.  The idea is you can take a C64/NTSC program with custom KNOBS/PITCH/SPEED settings (or even the default settings), and run them on the C128 with any hardware and hear the same thing.  This also implies you can take a C128-Version program with custom speech settings and run them on different C128 hardware and get the same sound.

CPUFIX is automatically called once: when you install SAM 128 or Reciter 128.  If you later change settings (for example, switch the CPU speed from SLOW / 1MHz to FAST / 2MHz) then you will need to manually call CPUFIX.  I was temped to have the CPUFIX called every time that SAM / Reciter is called to speak, but decided not to do so because CPUFIX will (most importantly) destroy any custom settings to NOISES and TIMEBASE, and it will slow things down a tiny bit (should not be human-noticeable).

See below for more info about NOISES and TIMEBASE.

For example, without a SuperCPU, but with Reciter 128 and the BASIC Wedge installed:

SAM (or rather Reciter) should sound the same in both cases.  Repeat the above example after removing both instances of ]CPUFIX (you should hear a dramatic difference).

The most versatile of the common routines is what I call Poker at 60946 ($EE12).  This changes various settings used directly by SAM (and indirectly by Reciter).  Just call the routine with an 'address value' (where to poke) and one or two values to be used (what to poke).  With the BASIC-Wedge, these can be accessed with custom BASIC keywords.  Those are listed below, for your information.  Trivia: two new entries are exclusive to my C128 version (NOISES and TIMEBASE).

Wedge Name
(A value)
X Value
Y Value Default
0 1~255
1~255 128, 128 Changes mouth (X) and throat (Y) of vowels and approximants
]LIGHTS 1 0~255 n/a
0 Keep VIC screen visible (any non-zero value)
]NOISES 2 1~255 1~255 7, 6 Set PCM period for all rushing and some plosives (X), and voiced fricatives (Y)
3 1~255 n/a
64 Sets the base phoneme wavelength (higher values = lower frequency)
4 1~255 n/a 72 Sets the base phoneme duration (higher values = slower speech)
5 1~255 n/a 2 (NTSC) Sets the playback time-base (affects both "pitch" and "speed")

For example, to make SAM speak a little faster than normal, you need to change the SPEED (at 'address' 4) to a value less than 72 (let's say 66).  In BASIC you can do it (without using the Wedge) like this:
  SYS 60946,4,66
assuming that BANK 1 is already in effect.

To use Poker from ML, just load the A, X, and Y registers with the values indicated in the table and then call the routine.  To repeat (translate) the previous example, do this:
LDA #4    ;poke 'Address' 4 (SPEED)
LDX #1    ;value to set
JSR $EE12 ;call Poker directly (only if running in BANK 1 -- otherwise use FAR_CALL)

This setting (changed with Poker 'address' 0) controls SAM's "mouth" and "throat" (to quote the original documentation).  This is a bit technical, but internally SAM maintains three separate waveforms, also called formants, which are used to generate the final audio output.  If you are familiar with programming the SID chip, these are analogous to SID's three voices (it would be interesting to re-write SAM to use the hardware voices).

The important thing to know is that the first two formants are sine waves and the third is a square wave.  The first "knob" value applies to the first sine wave ("mouth") while the second value applies to the other sine wave ("throat").  There is no way to manipulate the square waveform (I imagine this refers to "lips/tongue", but who knows?).  Changing KNOBS will adjust the relative frequency (pitch) of the following phonemes:
 WH  R  L
 W  Y  M  N

As you can see most of the affected phonemes are vowels or approximants (R,L,W,Y).  Also included are the nasal sounds M,N,NX.  Strangely, the "mixed D-T" phoneme DX is also affected (I guess because SAM will automatically create this phoneme when T or D is surrounded by vowels).  KNOBS acts similar to PITCH, but there are three main differences:
  • PITCH affects (almost) all phonemes, while KNOBS only affects those (vowel-ish ones) listed above
  • PITCH affects all three formants (waveforms) equally (but indirectly).  KNOBS directly changes formants 1 and 2 independently (and leaves the other alone).
  • PITCH uses wavelength (higher values = lower tone) while KNOBS uses frequency (higher values = higher tone)

The relative frequency set by KNOBS is the given value divided by 128.  So a value of 128 will set a relative frequency of 128/128 = 1.0 (i.e., the default / normal value).  A value of 64 will set a relative frequency of 64/128 = 0.5 (i.e., half the default frequency = lower tone).  A value of 255 will set the relative frequency at 255/128 = 1.9921875 (i.e., almost double the default frequency = higher tone).

Technical note: the absolute frequency will be relative to the phoneme's base frequency (6536 Hz / [global PITCH + phoneme's stress_relative_wavelength])... and the magic value of 6536 assumes you are using the correct TIMEBASE for your CPU.  And if you wonder why PITCH appears in the denominator of the above equation (and is added to a wavelength), it is because the PITCH setting is really wavelength (not frequency).

This setting (changed with Poker 'address' 2) controls the sound of some (parts of) "noisy" phonemes.  This is a bit technical, but internally SAM generates most sounds by combining three formants (see the Knobs section for more info).  Some phonemes, however, also (or only) use PCM playback.  Whereas the normal 3-formant method allows PITCH, SPEED, and volume to be adjusted for playback, the (1-bit) PCM playback is not affected by PITCH or SPEED (and the volume is fixed too).  Technical note: without knowing how the digital samples were encoded, it is unknown if the data is really PCM or PDM.  PDM would give superior quality compared to un-dithered PCM (however, dithered 1-bit PCM essentially is PDM).

The important thing to know is NOISES changes the time-base for two sets of 'noisy' phonemes (called X and Y for lack of better names), which changes both the pitch and speed of the phonemes.  The default values are 7 and 6 (intended for NTSC at 1MHz -- see also CPUFIX).  Greater values will result in slower speed and lower pitch (compared to default speech), and should be used if the CPU is set to FAST / 2MHz speed (or SuperCPU / 20MHz speed).   The affected phonemes are:

Value X Phonemes
Phoneme Duration PCM Table
S 241 1 5 8
SH 225 2 5 10
F 209 3 5 7
TH 185 3 5 7
/H 121 4 5 7
/X 145 5 5 7
CH.2 / *
113 2 5 10
P.2 25 3 5 7
T.2 25 1 5 8
Recommended NOISE value:

1 MHz
2 MHz
20 MHz
NTSC 7 18 220
PAL 6 17 211
Value Y Phonemes
Phoneme Duration PCM Table
Z 1~16 1 6 10
ZH 1~16 2 6 10
V 1~16 3 6 10
DH 1~16 3 6 10
J.2 1~16 2 6 10
Recommended NOISE value:

1 MHz
2 MHz
20 MHz
NTSC 6 16 196
PAL 5 15 188

As described under the "common" list of phonemes, SAM will internally expand some phonemes into 2 or 3 sub-phonemes (for lack of a better term... phone would be right for some, but not all).  The NOISES value only affects part 2 (and not all expanded phonemes, just those shown above) -- hence the tables include non-standard "phonemes" like CH.2.  From a phonetic (linguistic) point of view, NOISES applies to the fricatives (including the psudo-fricative H sounds), the affricates (CH and J), and two plosives (P and T).

You don't strictly need to know, but SAM has five separate PCM tables.  Different "noisy" phonemes use different PCM tables; tables 1 to 3 are shared by multiple phonemes, while tables 4 and 5 are each used by a single phoneme.  You also don't really need to know the duration value, but hopefully you will find it educational.  The "duration" is the number of bytes that will be read from the PCM table, and each byte (8 bits) represents 8 PCM samples to play (each bit is rendered with a fixed amplitude for that (sub)phoneme).  Both amplitude values are fixed for the voiced phonemes, although their duration is variable.  For the unvoiced ones, the duration is fixed while the amplitude high varies by PCM table (amplitude low is fixed).

The "Value X Phonemes" are what I think of as "pure noise".  They include all "rushing" phonemes, part 2 of the affricate CH, and part 2 of the plosives P and T.  All are classified as "unvoiced".  I call them "pure noise" because when SAM renders them, he completely skips the normal 3-formant code and immediately plays a fixed number of samples from the indicated PCM table.  This means the normal affects of PITCH, SPEED, TIMEBASE, and internal amplitude are completely ignored.  Also the duration of each is fixed, and relatively long.  See my Technical page for details.

Included under the "Value X Phonemes" is the undocumented phoneme * (asterisk).  This is simply the second sub-phone of "CH".  Hence it appears on the same row as CH.2.

The "Value Y phonemes" are what I call "voicey noise".  They include the fricatives (Z, ZH, V, DH), and part 2 of the affricate J.  These are all classified as "voiced".  These phonemes work differently than the "pure noise" ones.  For these, SAM begins playing the phoneme using the normal 3-formant algorithm.  This means they are affected by PITCH, SPEED, TIMEBASE, and the internal amplitude.  However, after 75% of the phoneme's base wavelength has been rendered, SAM will switch to a PCM playback routine.  The duration of the PCM-part of the phoneme is very short (compared to those of the X-Values).  This is because 75% of the waveform has already been played.  The duration is not fixed for each phoneme; it is calculated as base wavelength / 16 + 1 (see the section on PITCH to learn more).. Again, the duration tells the number of bytes to read from the PCM table and playback.  And although the amplitude of each bit is again fixed, different values are used than with the "pure noise" (Value X phonemes).  See my Technical page for details.

Technical note (okay to ignore): assuming the CPU is running at exactly 1.00 MHz, the "X-Phonemes" have a 17.4 kHz (sample) bit rate, while the "Y-Phonemes" have a 19.2 kHz bit rate.  It is not known if the audio samples were actually captured at these (or similar) two rates, or more likely (my opinion) the difference is sloppy programming (i.e., the samples were captured at one single rate, but coding differences made playback rates differ).  The code uses simple 'bit-banging' of the SID volume register which does not allow SID's internal filters to affect the audio.  However, analog circuits in C128 audio output (and possibly in your TV/monitor/speakers) will low-pass filter the audio.  I don't think it is possible to accurately describe the filtering due to all the unknown variables.  Each table contains a different mixture of high and low frequencies.  It would be interesting to do a spectral analysis on them...

As some practical examples you can use
  SYS 60946,2,18,16

to change the NOISE setting for 2MHz (FAST) CPU speed (NTSC),

or you can use
  SYS 60946,2,7,6
to restore the NOISE setting to the default 1MHz (SLOW) CPU speed.  Both examples assume that BANK 1 is already in effect.

This setting (changed with Poker 'address' 3) controls the pitch of most phonemes spoken by SAM/Reciter (see the section on NOISES for a list of unaffected or partially affected phonemes).  PITCH sets the global base wavelength.  Thus, larger values will generate a lower pitch.  This value is added to a phoneme-specific wavelength modifier for each affected phoneme.  The phoneme-specific wavelength modifier (which may be negative) is one of 10 values, based on stress of the phoneme.  Some technical info you may ignore: this includes not only stress (if any) given explicitly in the input text, but possibly small (+1) stress changes for certain combinations of phonemes.  SAM's three formants (waveforms) will generate higher-frequency (shorter wavelength) harmonics than the phoneme's final wavelength.

Values lower than about 32 or greater than about 115 may cause erroneous output (depends on stress of phonemes).  Logically (the way I'm thinking) PITCH values up to 243 should be okay, but it seems there is a bug in SAM for effective pitch values around 128 (I need to research).  With the default PITCH value of 64, a phoneme with stress-1 (greatest stress) will have half the fundamental wavelength (double the frequency) of an unstressed phoneme.  (Note this stres-1 = double frequency relation is not true with other PITCH values).  If my calculations are correct, the fundamental wavelength (really time period) is approximately 153 microseconds times the effective value (PITCH + delta wavelength).  Thus, SAM's default wavelength is 9.792 ms (which is a frequency of 102 Hz).  Or in other words, the fundamental frequency of a typical phoneme is about 6536 Hz divided by the effective pitch.  (The calculations assume the recommended TIMEBASE values for the CPU).

This first BASIC example makes SAM sound more feminine:
  SYS 60946,3,32

This second example makes SAM sound like a giant:
  SYS 60946,3,110
Both examples assume that BANK 1 is active.

This setting (changed with Poker 'address' 4) controls the "speed" of most phonemes spoken by SAM/Reciter (see the section on NOISES for a list of unaffected or partially affected phonemes).  SPEED sets the global phoneme hold period (duration).  Thus, larger values will generate slower speech.  This value is added to one of two possible phoneme-specific hold periods.  One period is used for unstressed phonemes while a second (usually longer) period is used for stressed phonemes (see the listing of phonemes for these two values).  Besides this, a phoneme's hold period may be modified in several ways depending on how phonemes combine.  Unlike a phoneme's pitch which can only have 9 possible values, a phoneme's hold period has many possible values.

The SPEED value should be less than about 160 to prevent distorted audio (actual maximum depends on phonemes used and their stress level).  Because the longest duration for a single phoneme part is 16, using values for SPEED of 16 or less means the individual phoneme's time period will be the main factor controlling speed (in other words, the global SPEED doesn't really control SAM's general speed).  As a practical matter (with recommended TIMEBASE for your CPU speed), values less than about 32 will generate speech so fast it will be (nearly) indecipherable.

This first BASIC example makes SAM speak quickly:
  SYS 60946,4,40

This second example makes SAM speak slowly:
  SYS 60946,4,120
Both examples assume that BANK 1 is active.

This setting (changed with Poker 'address' 5) controls the time-base (sample period) for generation of most phonemes spoken by SAM/Reciter (see the section on NOISES for a list of unaffected or partially affected phonemes).  A larger value makes affected phonemes have a lower pitch and slower speed.  A smaller value makes the affected phones have a higher pitch and faster speed (this is analogous to the PITCH and SPEED settings).  If you've ever played a phonograph at the wrong speed, then you should have a good idea how this setting affects the audio output.  This setting was added to the C128 version to allow for correct playback at 2MHz CPU speed.  Of course you can also use it for general alteration of SAM's voice.

The default TIMEBASE is 2 so as to be compatible with the C64 version.  Here are the recommended settings for normal sound (see also CPUFIX):

1 MHz
2 MHz
20 MHz
NTSC 2 30 582
PAL 1 28 558
What these values do is control the speed of SAM's main render loop, such that the fundamental frequency (in Hertz) can still be calculated as 6536 / pitch_value (wavelength).  See the section about PITCH for more details.

Note the recommended SLOW PAL value of 1 is if you want that frequency calculation to work.  However, the C64 version has no PAL correction, so PAL users familiar C64 SAM might prefer the default value of 2.  Now that I think about it, experienced C64 PAL users might want to make NTSC SAM sound like PAL! In that case, try using a value of 3 for SLOW CPU speed.

Note that because of the SuperCPU, values greater than 255 may be needed.  So the value must be split into a low-byte and high-byte.  For example, to use 2MHz (FAST) CPU speed on an NTSC machine, change the TIMEBASE to 30, like this:
  SYS 60946,5, 30, 0

Another example, to use 20MHz (SuperCPU) speed on an NTSC machine, change the TIMEBASE to 582, like this:
  SYS 60946,5, 582 AND 255, 582/256

The same example again, but in ML:
LDA #5    ;poke 'Address' 5 (TIMEBASE)
LDX #<582 ;value low
LDY #>582 ;value high
JSR $EE12 ;call Poker directly (only if running in BANK 1 -- otherwise use FAR_CALL)

All three examples assume that BANK 1 is active.

Note: TIMEBASE does not affect the pitch and speed of a few (parts of) 'noisy' phonemes.  So if you are adjusting for a change in CPU speed, the NOISES also need to be changed (or simply call CPUFIX).

Project64 documentation of (C64) SAM.
Find out more about SAM+Reciter (C64) on Wikipedia!

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