Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes ( itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM  itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C



Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
\FF

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
\C2D\FF

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
E\FE\ED\F2B

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
C\ED\FA\A0\C8\ED\FA\A9

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
E

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
\DC\FF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"BA\B3\C8\ED\F2\B3\C3\A0

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
E

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"E\CD\CF

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"D\F8\C9E\A7\C8\FE

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
B

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
E

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
B\C5\D5\E5\CD\B2

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
B\E1\D1\C1\C2\D9\C9\A0ADF

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
\D5

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
\D1 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"A\F4\C9 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\A8\CDB

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
E\B9\F5AC itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
D\FC\EB\ED\B0\C9\C5E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
E\EB\EBD\F8\CB itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"A\CB itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"B\F8\C1\C9 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\FF

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
\C5

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
E

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"A

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
FC

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
E\FFF\EF\C1\B9\D8FFE

Voice

Developer(s): Brad Bennett
Date: 1983
Type: Program
Platform(s): TS 1000

This program implements a voice recognition system using machine code routines embedded in a REM statement at line 1. The system samples audio through the ZX81/TS1000 speaker/microphone port, builds “voiceprints” by recording a spoken word eight times and averaging the results into a 1412-element array, then compares new samples against up to ten stored voiceprints to identify recognised words. Machine code entry points at USR 16520, USR 16575, USR 16615, USR 16641, and USR 16707 handle audio sampling, display, filing, and recognition respectively, with the code loaded at address 16520 (0x4088) within the REM data. The BASIC shell provides a five-option menu using computed GOTO arithmetic (line 75: `GOTO S*200`) to dispatch to voiceprint display, filing, recognition, file clearing, and string listing routines.


Program Analysis

Program Structure

The program is divided into six functional modules, dispatched by a computed GOTO S*200 at line 75. Each module occupies a block starting at a multiple of 200:

LinesModule
1–5Machine code payload (REM), warnings, integrity check
10–80Initialisation, menu, and dispatch
200–275Voiceprint Display
400–520Voiceprint Filing (record and store)
600–640Recognition
800–830Clear Files
1000–1040Display String File
1200STOP (option 6)
1300–1310User instructions (in inverse video REM text)
9000–9050SAVE and author credits

Machine Code Payload

The entire machine code routine is stored in the REM statement at line 1, beginning at address 16514 (the start of the REM text). The first six bytes (\1C × 6) are padding; the executable code starts at offset 6 within the REM, placing key entry points at the following addresses:

Address (decimal)Address (hex)Purpose
165200x4088Audio sampler — fills screen RAM with audio data
165750x40BFVoiceprint display renderer
166150x40E7Store one of 8 audio samples to voiceprint buffer
166410x4101Average 8 samples and file voiceprint at position R
167070x4143Recognition — compare live sample against stored prints

Line 5 performs a checksum/integrity test: IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD". Address 16758 (0x4176) points to a short routine at the end of the REM block that returns a value in the BC register used as the USR result; if the machine code loaded correctly it returns 64.

Audio Sampling Technique

The sampler at USR 16520 reads from the ZX81 keyboard/tape port (IN instruction targeting port 0xFE or similar) in a tight Z80 loop, writing samples directly to the 1K display file starting at 0x5800 (decimal 22528). This repurposes the screen RAM as a 768-byte sample buffer. The BASIC variables POKE 16576/POKE 16577 set a 16-bit pointer (little-endian) that the machine code uses to know where in screen RAM to write, allowing the display offset to be shifted by menu options 5 and 8 (lines 265–270).

Voiceprint Filing Logic

Filing (lines 400–485) records the spoken word eight times in a loop (FOR I=0 TO 7). Each iteration calls the sampler (USR 16520), POKEs the loop index into address 25997 (POKE 25997,I), then calls USR 16615 to accumulate the sample into an averaging buffer. After the loop, POKE 25996,R sets the file slot number and USR 16641 divides the accumulated samples and stores the result. Up to 10 voiceprints are supported, indexed 1–10 and paired with label strings in the DIM T$(10,10) array.

Recognition

The recognition loop (lines 600–640) repeatedly calls the sampler and then USR 16707, which compares the live screen-RAM sample against all stored voiceprints. It returns the best-match index via a POKE to address 25999; the BASIC reads this with PEEK 25999+1 (adding 1 to convert from 0-based to 1-based) and prints the corresponding T$ label. Pressing any key returns to the menu.

Key BASIC Idioms

  • Computed GOTO: GOTO S*200 (line 75) dispatches to each module without a chain of IF statements.
  • FAST/SLOW toggling: FAST is set before all machine code calls and SLOW before any display or input, managing the ZX81 display driver correctly.
  • PAUSE 30 between samples (line 475) gives the user a brief gap between the eight recording passes.
  • Clear files (lines 815–825) POKEs zeros across addresses 26000–26640 (the voiceprint data area) in addition to clearing the T$ string array.

Memory Map Summary

Address rangeContents
16514–16758Machine code in REM line 1
22528–23295Display file (reused as audio sample buffer)
25996File slot parameter for USR 16641
25997Sample iteration index (0–7) for USR 16615
25999Recognition result index written by USR 16707
26000–26640Voiceprint data store (10 × ~64 bytes)

Bugs and Anomalies

  • Line 75 dispatches GOTO S*200 for S=1–6, mapping option 6 to line 1200 (STOP). However, option 5 maps to line 1000, not 1000 — this is correct. Option 3 maps to line 600, option 4 to line 800, all consistent.
  • The recognition display uses T$(PEEK 25999+1). Since PEEK has higher precedence than +, this correctly evaluates as T$((PEEK 25999)+1).
  • Line 1310’s instructions contain the typo “RECGONIZED” (twice: “RECGONIZED” and “RECGONITION”) — these are in the original inverse-video REM text.
  • The DIM C(1412) at line 10 allocates a floating-point array of 1412 elements (each 5 bytes = 7060 bytes). This array does not appear to be referenced anywhere in the BASIC; it likely exists purely to reserve RAM for the machine code’s voiceprint working area above RAMTOP, or is a vestige of an earlier pure-BASIC version.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Related Articles

Simple speech recognition hardware and program for ZX/TS computers (with at least 16K RAM).

Related Content

Image Gallery

Voice

Source Code

       1 REM \1C\1C\1C\1C\1C\1C\21\00\58\06\FF\36\00\05\23\C2\8D\40\06\FF\21\00\58\0E\FE\ED\78\F2\9B\40\2C\ED\78\FA\A0\40\34\05\C8\ED\78\FA\A9\40\2E\00\11\DC\FF\1B\7A\B3\C8\ED\78\F2\B3\40\C3\A0\40\21\00\58\0E\00\1E\40\CD\CF\40\23\0C\1D\20\F8\C9\7E\A7\C8\FE\2B\38\02\3E\2B\47\C5\D5\E5\CD\B2\0B\E1\D1\C1\05\C2\D9\40\C9\06\40\21\A0\61\3A\8D\65\85\6F\11\00\58\D5\11\08\00\19\D1\1A\77\13\05\20\F4\C9\01\28\64\21\A8\61\CD\26\41\7B\02\03\3E\68\B9\20\F5\3A\8C\65\01\40\00\21\50\65\09\3D\20\FC\11\28\64\EB\ED\B0\C9\C5\3E\08\01\00\00\11\00\00\4E\EB\09\EB\3D\23\20\F8\06\03\97\CB\1A\CB\1B\05\20\F8\C1\C9\21\90\65\01\FF\00\C5\11\00\58\0E\00\06\40\1A\96\30\02\2F\3C\81\30\02\3E\FF\4F\23\13\05\20\EF\79\C1\B9\32\D8\59\30\05\4F\78\32\8F\65\04\3E\0A\B8\20\D4\C9\21\88\40\97\06\EE\86\23\05\20\FB\4F\C9\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C\1C
       2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N
       3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 
       4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 
       5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD"
      10 DIM C(1412)
      15 DIM T$(10,10)
      20 CLS 
      25 PRINT AT 7,1
      30 PRINT TAB 12;"MENU"
      35 PRINT TAB 6;"1. VOICEPRINT DISPLAY"
      40 PRINT TAB 6;"2. VOICEPRINT FILE"
      45 PRINT TAB 6;"3. RECOGNITION"
      50 PRINT TAB 6;"4. CLEAR FILES"
      55 PRINT TAB 6;"5. DISPLAY STRING FILE"
      60 PRINT TAB 6;"6. STOP"
      62 PRINT ,,,,,,TAB 8;"INPUT SELECTION"
      65 FAST 
      70 INPUT S
      75 IF S<=6 THEN GOTO S*200
      80 GOTO 70
     199 REM **VOICEPRINT DISPLAY**
     200 RAND USR 16520
     205 LET K=22528
     210 CLS 
     215 POKE 16577,INT (K/256)
     220 POKE 16576,K-256*INT (K/256)
     225 RAND USR 16575
     230 PRINT AT 2,20;"AGAIN? (Y/N)"
     235 SLOW 
     240 IF INKEY$="" THEN GOTO 240
     245 FAST 
     250 LET B$=INKEY$
     255 IF B$="N" THEN GOTO 20
     260 IF B$="Y" THEN GOTO 200
     265 IF B$="5" AND K<=22719 THEN LET K=K+1
     270 IF B$="8" AND K>=22529 THEN LET K=K-1
     275 GOTO 210
     399 REM **VOICEPRINT FILE**
     400 CLS 
     405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED"
     410 INPUT Z$
     415 PRINT AT 12,1;"ENTER FILE POSITION"
     420 INPUT R
     425 LET T$(R)=Z$
     430 PRINT AT 14,1;"PRESS ENTER TO BEGIN"
     435 INPUT F$
     440 CLS 
     445 FOR I=0 TO 7
     450 RAND USR 16520
     455 POKE 25997,I
     460 RAND USR 16615
     465 PRINT AT 10,16;I+1
     470 SLOW 
     475 PAUSE 30
     480 FAST 
     485 NEXT I
     490 POKE 25996,R
     495 RAND USR 16641
     500 PRINT AT 12,13;"AGAIN (Y/N)"
     505 INPUT B$
     510 IF B$="Y" THEN GOTO 400
     515 IF B$="N" THEN GOTO 20
     520 GOTO 505
     599 REM **RECOGNITION**
     600 RAND USR 16520
     605 RAND USR 16707
     610 CLS 
     615 PRINT AT 12,10;T$(PEEK 25999+1)
     620 SLOW 
     625 PAUSE 60
     630 FAST 
     635 IF INKEY$<>"" THEN GOTO 20
     640 GOTO 600
     799 REM **CLEAR FILES**
     800 FOR I=1 TO 10
     805 LET T$(I)=""
     810 NEXT I
     815 FOR I=26000 TO 26640
     820 POKE I,0
     825 NEXT I
     830 GOTO 20
     999 REM **DISPLAY STRING**
    1000 CLS 
    1005 FOR I=1 TO 10
    1010 PRINT AT (5+I),10;I;". ";T$(I)
    1015 NEXT I
    1020 PRINT ,,,,"    PRESS ANY KEY TO CONTINUE"
    1025 SLOW 
    1030 IF INKEY$="" THEN GOTO 1030
    1035 FAST 
    1040 GOTO 20
    1200 STOP 
    1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 
    1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!!
    1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\..
    9000 SAVE "VOIC%E"
    9010 LIST 1300
    9020 REM ROBERT SCHIMKE...
    9030 REM 1005 WESTWIND CIRCLE
    9040 REM PLACENTIA,CALIFORNIA
    9050 REM 9267O  USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top
A\B8\D4\C9\EE\FBF\C9 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-57759 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C 2 REM % %U%S%E% %G%O%T%O% %2%0% %D%O% %N%O%T% %R%U%N 3 REM % %O%R% %W%I%L%L% %C%L%E%A%R% %V%O%I%C%E%-% % 4 REM % %P%R%I%N%T%S%.% %A%F%T%E%R% %S%A%V%I%N%G% % 5 IF USR 16758<>64 THEN PRINT AT 10,10;"BAD LOAD" 10 DIM C(1412) 15 DIM T$(10,10) 20 CLS 25 PRINT AT 7,1 30 PRINT TAB 12;"MENU" 35 PRINT TAB 6;"1. VOICEPRINT DISPLAY" 40 PRINT TAB 6;"2. VOICEPRINT FILE" 45 PRINT TAB 6;"3. RECOGNITION" 50 PRINT TAB 6;"4. CLEAR FILES" 55 PRINT TAB 6;"5. DISPLAY STRING FILE" 60 PRINT TAB 6;"6. STOP" 62 PRINT ,,,,,,TAB 8;"INPUT SELECTION" 65 FAST 70 INPUT S 75 IF S<=6 THEN GOTO S*200 80 GOTO 70 199 REM **VOICEPRINT DISPLAY** 200 RAND USR 16520 205 LET K=22528 210 CLS 215 POKE 16577,INT (K/256) 220 POKE 16576,K-256*INT (K/256) 225 RAND USR 16575 230 PRINT AT 2,20;"AGAIN? (Y/N)" 235 SLOW 240 IF INKEY$="" THEN GOTO 240 245 FAST 250 LET B$=INKEY$ 255 IF B$="N" THEN GOTO 20 260 IF B$="Y" THEN GOTO 200 265 IF B$="5" AND K<=22719 THEN LET K=K+1 270 IF B$="8" AND K>=22529 THEN LET K=K-1 275 GOTO 210 399 REM **VOICEPRINT FILE** 400 CLS 405 PRINT AT 10,1;"ENTER STRING TO BE RECOGNIZED" 410 INPUT Z$ 415 PRINT AT 12,1;"ENTER FILE POSITION" 420 INPUT R 425 LET T$(R)=Z$ 430 PRINT AT 14,1;"PRESS ENTER TO BEGIN" 435 INPUT F$ 440 CLS 445 FOR I=0 TO 7 450 RAND USR 16520 455 POKE 25997,I 460 RAND USR 16615 465 PRINT AT 10,16;I+1 470 SLOW 475 PAUSE 30 480 FAST 485 NEXT I 490 POKE 25996,R 495 RAND USR 16641 500 PRINT AT 12,13;"AGAIN (Y/N)" 505 INPUT B$ 510 IF B$="Y" THEN GOTO 400 515 IF B$="N" THEN GOTO 20 520 GOTO 505 599 REM **RECOGNITION** 600 RAND USR 16520 605 RAND USR 16707 610 CLS 615 PRINT AT 12,10;T$(PEEK 25999+1) 620 SLOW 625 PAUSE 60 630 FAST 635 IF INKEY$<>"" THEN GOTO 20 640 GOTO 600 799 REM **CLEAR FILES** 800 FOR I=1 TO 10 805 LET T$(I)="" 810 NEXT I 815 FOR I=26000 TO 26640 820 POKE I,0 825 NEXT I 830 GOTO 20 999 REM **DISPLAY STRING** 1000 CLS 1005 FOR I=1 TO 10 1010 PRINT AT (5+I),10;I;". ";T$(I) 1015 NEXT I 1020 PRINT ,,,," PRESS ANY KEY TO CONTINUE" 1025 SLOW 1030 IF INKEY$="" THEN GOTO 1030 1035 FAST 1040 GOTO 20 1200 STOP 1300 REM % %S%Y%N%C% %N%O%V%/%D%E%C% %8%3% 1305 REM \!!% %B%R%A%D% %B%E%N%N%E%T%T% \!!\!! 1310 REM % %U%S%E% %T%A%P%E% %R%E%C%O%R%D%E%R% %E%A%R% %T%O% %E%A%R%.% %U%S%E% %B%L%A%N%K% %T%A%P%E% %A%N%D% %S%E%T% % %T%O% %R%E%C%O%R%D%.% %E%N%T%E%R% %2%.% %A%N%D% %S%P%E%A%K% % % %W%O%R%D% %8% %T%I%M%E%S% %T%O% %M%A%K%E% %V%O%I%C%E%P%R%I%N%T%.%O%N%E% %S%A%Y%A%B%L%E% %W%O%R%D%S% %W%O%R%K% %B%E%S%T%.% % % % %E%N%T%E%R% %3%.% %A%N%D% %R%E%P%E%A%T% %W%O%R%D%.% %T%H%E% % % %W%O%R%D% %W%I%L%L% %P%R%I%N%T% %T%O% %S%C%R%E%E%N% %I%F% %I%T% %I%S% %R%E%C%G%O%N%I%Z%E%D%.% %E%N%T%E%R% %1%.% %T%O% %S%E%E% % %V%O%I%C%E%P%R%I%N%T%.% %S%P%E%A%K% %W%O%R%D% %O%R% %S%O%U%N%D% %I%N%T%O% %S%P%E%A%K%E%R%.% %W%I%L%L% %D%I%S%P%L%A%Y% %V%O%I%C%E%P%R%I%N%T%.% % %U%S%E% %C%L%E%A%R% %B%E%F%O%R%E% %S%A%V%E% %I%F%N%O%T% %S%A%V%I%N%G% %V%O%I%C%E%P%R%I%N%T%S%.% %P%R%O%G%R%A%M% %W%I%L%L% %S%A%V% %1%0% %V%O%I%C%E%P%R%I%N%T%S%.% % % % % % % % %A%L%T%E%R%N%A%T%E% %A%M%P% %M%I%K%E% %M%I%G%H%T% %M%A%K%E% % % %R%E%C%G%O%N%I%T%I%O%N% %B%E%T%T%E%R%.\..\..\..\..\..\..\..\..\..\..\..\..\.. 9000 SAVE "VOIC%E" 9010 LIST 1300 9020 REM ROBERT SCHIMKE... 9030 REM 1005 WESTWIND CIRCLE 9040 REM PLACENTIA,CALIFORNIA 9050 REM 9267O USA

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top