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:
| Lines | Module |
|---|---|
| 1–5 | Machine code payload (REM), warnings, integrity check |
| 10–80 | Initialisation, menu, and dispatch |
| 200–275 | Voiceprint Display |
| 400–520 | Voiceprint Filing (record and store) |
| 600–640 | Recognition |
| 800–830 | Clear Files |
| 1000–1040 | Display String File |
| 1200 | STOP (option 6) |
| 1300–1310 | User instructions (in inverse video REM text) |
| 9000–9050 | SAVE 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 |
|---|---|---|
| 16520 | 0x4088 | Audio sampler — fills screen RAM with audio data |
| 16575 | 0x40BF | Voiceprint display renderer |
| 16615 | 0x40E7 | Store one of 8 audio samples to voiceprint buffer |
| 16641 | 0x4101 | Average 8 samples and file voiceprint at position R |
| 16707 | 0x4143 | Recognition — 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:
FASTis set before all machine code calls andSLOWbefore 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 range | Contents |
|---|---|
| 16514–16758 | Machine code in REM line 1 |
| 22528–23295 | Display file (reused as audio sample buffer) |
| 25996 | File slot parameter for USR 16641 |
| 25997 | Sample iteration index (0–7) for USR 16615 |
| 25999 | Recognition result index written by USR 16707 |
| 26000–26640 | Voiceprint data store (10 × ~64 bytes) |
Bugs and Anomalies
- Line 75 dispatches
GOTO S*200for 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). SincePEEKhas higher precedence than+, this correctly evaluates asT$((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 aboveRAMTOP, or is a vestige of an earlier pure-BASIC version.
Content
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
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
\FF
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
\C2D\FF
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
E\FE\ED\F2B
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
C\ED\FA\A0\C8\ED\FA\A9
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
E
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
\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
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
E
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
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
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
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
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
B
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
E
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
B\C5\D5\E5\CD\B2
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
B\E1\D1\C1\C2\D9\C9\A0ADF
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
\D5
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
\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
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
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"
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
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"
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
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
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
\C5
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
E
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
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
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
FC
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
E\FFF\EF\C1\B9\D8FFE
Skip to content
Voice
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:
Lines Module 1–5 Machine code payload (REM), warnings, integrity check 10–80 Initialisation, menu, and dispatch 200–275 Voiceprint Display 400–520 Voiceprint Filing (record and store) 600–640 Recognition 800–830 Clear Files 1000–1040 Display String File 1200 STOP (option 6) 1300–1310 User instructions (in inverse video REM text) 9000–9050 SAVE 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 16520 0x4088 Audio sampler — fills screen RAM with audio data 16575 0x40BF Voiceprint display renderer 16615 0x40E7 Store one of 8 audio samples to voiceprint buffer 16641 0x4101 Average 8 samples and file voiceprint at position R 16707 0x4143 Recognition — 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 range Contents 16514–16758 Machine code in REM line 1 22528–23295 Display file (reused as audio sample buffer) 25996 File slot parameter for USR 16641 25997 Sample iteration index (0–7) for USR 16615 25999 Recognition result index written by USR 16707 26000–26640 Voiceprint 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
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.
People
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.
