Music Program from Echos Sinclair magazine

Discussion about ZX80 / ZX81 Software
Post Reply
David G
Posts: 545
Joined: Thu Jul 17, 2014 7:58 am
Location: 48 North

Music Program from Echos Sinclair magazine

Post by David G »

English translation: Music on TV Program
Programme de Musique sur TV

This is a proof-of-concept for playing 1-bit sounds with an unmodified ZX81 (or with emulator such as EightyOne). Although the article is tagged "Music Program" ("Programme Music"), the text clarifies that it only "generates sounds on your television" (Son sur TV), and is intended to be developed further

Listing1.p
(1.3 KiB) Downloaded 40 times

Listing1.p matches the Figure 1 listing in the article, but ... because this program may not work first time, I enhanced it with directions on the screen (D_FILE contents only, BASIC is unmodified)
* The program must not be used in SLOW mode, so enter FAST first
* On first use, use GOTO 100 per the instructions in the magazine article


SON.P from telecharger matches the Figure 2 listing


What I found most interesting about this how they approached a type-in that has machine code:
  • the machine code loader is built-in, so the listing is compatible with pure ASCII
  • Listing B1 appears to be a table of some kind, but is actually a list of hex-digits in two columns, to be used as a check for comparing the digits entered into A$

from Echos Sinclair magazine N. 1 pages 12-13
Music Program
Image


A program in machine language, it will allow you to generate sounds on your television by pressing certain keys on the keyboard.

This program is in reality only a draft that we hope to be able to develop thanks to all your ideas in this same section during future publications. You will discover: two major drawbacks:

-- the first being the use of the <<port>> output of the television. We will therefore not be able to view a screen display while using the program.

-- the second can be easily resolved, it is a return to Basic during execution. Once the program is started, it is impossible to end use. All you have to do is unplug your machine. You will only have to insert the test of a key in your loop so that the program returns to Basic.


Programming :

Programming in machine language requires some explanation.

The three listings, attached, show you the evolution of this programming. The 1st step is the entry as proposed by listing no. 1 by comparing the characters of the variable A$ (line 200) to those of the table. (listing B1)

Listing B1

Code: Select all

9B      20
89      FD
73      C9
69      CD
00      BB
93      02
7E      44
00      4D
5E      51
00      14
3B      28
31      F7
26      CD
24      BD
00      07
00      11
36      04
2C      40
00      19
00      46
00      AF
OF      B8
16      28
1E      EB
00      DB
0A      FF
OC      CD
12      A9
1A      40
00      D3
00      FF
00      CD
41      A9
4C      40
00      18
38      EO
3C
46
53
78
3D
Line 10 : reserve memory space (77 bytes, after the REM). Line 100 : 100 LET A$ = <<9B89...>> storage of hexadecimal codes corresponding to the mnemonics of the microprocessor Z 80 A.

Lines 300 to 800 character : decoding and hexadecimal calculation, transfer by line 600 POKE to address Q (1st address 16514).
Listing 1.jpg
Listing 1

Code: Select all

  10 REM 11111111111111111111111
11111111111111111111111111111111
11111111111111111111111
 20 RAND USR 16558
 100 LET Q=16514
 200 LET A$="9B89736900937E005E0
03B3126240000362C0000000F161E000
A0C121A000000414C00383C4653783D2
0FDC9CDBB02444D511428F7CDBD07110
4401946AFB828EBDBFFCDA940D3FFCDA
94018E0"
 300 FOR P=1 TO LEN A$-1 STEP 2
 400 LET X=CODE A$(P)-28
 500 LET Y=CODE A$(P+1)-28
 600 POKE Q,16*X+Y
 700 LET Q=Q+1
 800 NEXT P

Execution:

The first execution is done by a GO TO 100. The program will extract two by two the characters of the variable A$ and transfer the character corresponding to the Hex code (listing 2).
Listing 2.jpg
Listing 2

Code: Select all

  10 REM ÓÁsi ËA8  QG   ?-2 ½£>,
   INKEY$ ? SW??xX4CLEAR TAN LN 
ø¢???=CRUN LN ú¹)¤RND;?ëôC FOR 
<=COPY LN åRNDPEEK COPY LN åRND
/ STEP
  20 RAND USR 16558
 100 LET Q=16514
 200 LET A$="9B89736900937E005E0
03B3126240000362C0000000F161E000
A0C121A000000414C00383C4653783D2
0FDC9CDBB02444D511428F7CDBD07110
4401946AFB828EBDBFFCDA940D3FFCDA
94018E0"
 300 FOR P=1 TO LEN A$-1 STEP 2
 400 LET X=CODE A$(P)-28
 500 LET Y=CODE A$(P+1)-28
 600 POKE Q,16*X+Y
 700 LET Q=Q+1
 800 NEXT P

All we have to do is:
- delete lines 100 to 800 (listing no. 3),
- put the machine in FAST mode,
- save the program <<object>> on magnetic tape,
- execute the program by RUN,
- increase the volume of the television
and << play the piano >>.
Listing 3.jpg
Listing 3

Code: Select all

  10 REM ÓÁsi ËA8  QG   ?-2 ½£>,
   INKEY$ ? SW??xX4CLEAR TAN LN 
ø¢???=CRUN LN ú¹)¤RND;?ëôC FOR 
<=COPY LN åRNDPEEK COPY LN åRND
/ STEP 1
  20 RAND USR 16558

The program runs on 1 K RAM but will give you a better sound by executing it with your additional memory 16 K RAM.
[edit: update Listing1.p (accidently posted Listing2.p)]
Attachments
Programme Music.jpg
Programme Music.jpg (21.29 KiB) Viewed 703 times
David G
Posts: 545
Joined: Thu Jul 17, 2014 7:58 am
Location: 48 North

Re: Music Program from Echos Sinclair magazine

Post by David G »

OK, so when I initially ran this program (SON.P from the Abandon Listings site "Programme de Musique sur TV"), I was not impressed. It didn't work for me. So I spent some time translating and going through the article, and got it working (it must be run in FAST mode). Then it works, but seemed to be just another program of the type "press the keys and hear some random notes". The notes played by each key are somewhat random sounding, not very harmonious

David G wrote: Thu Nov 28, 2024 10:14 pm What I found most interesting about this how they approached a type-in that has machine code:
  • the machine code loader is built-in, so the listing is compatible with pure ASCII
  • Listing B1 appears to be a table of some kind, but is actually a list of hex-digits in two columns, to be used as a check for comparing the digits entered into A$

BUT I WAS WRONG

It is far more interesting. While going through the (very short) machine language, it seemed to have a typo in the last statement, the main loop. The JR was off by one. And yet it still worked (execution of those opcodes are harmless), so the sound still played


Next, I noticed it was getting notes from a table at the beginning of the REM. It was puzzling. The code was loading something from RAMTOP (address $4004) which didn't make sense ... no, not from RAMTOP, but the number 4004 was used with this table somehow. It finally dawned on me that the keypresses are used as the index into the table

The table is 39 bytes long. The ZX81 keyboard has 40 keys. Coincidence?

Well, some of the keys don't make a sound. Mapped out on paper
-SD-FG
ZXCVB
Hey, that pattern is like a piano keyboard, with the "black keys" on the 2nd row
I wonder ... correcting the errant JR. Yep, now the keyboard is in tune
David G
Posts: 545
Joined: Thu Jul 17, 2014 7:58 am
Location: 48 North

Re: Music Program from Echos Sinclair magazine

Post by David G »

Now I know why the original French text says "pianotier" (play the piano). All makes sense now


To correct the machine language, change the end of A$ in Line 200 from:

E0

to

DF


with DF

Code: Select all

|         - -     C#5     D#5     - -     F#5     G#5     A#5     - -     - -     - -    |
|        +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   |
|        | A |   | S |   | D |   | F |   | G     | H |   | J |   | K |   | L |    N/L    |
|        +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   |
|                                                                                        |
|           C 5     D 5-    E 5     F 5     G 5     A 5     B 5-    C 6--   - -          |
|  +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+         |
|  SHIFT   | Z |   | X |   | C |   | V     | B |   | N |   | M |   | . |   SPACE         |
|  +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+   +---+         |
|                                                                                        |
|                                                                                        |
+----------------------------------------------------------------------------------------+
David G
Posts: 545
Joined: Thu Jul 17, 2014 7:58 am
Location: 48 North

Re: Music Program from Echos Sinclair magazine

Post by David G »

Here is the reverse-engineered Assembly Language of the machine language bytes

These bytes:

Code: Select all

 200 LET A$="9B89736900937E005E003B3126240000362C0000000F161E000A0C121A000000414C00383C4653783D20FDC9CDBB02444D511428F7CDBD071104401946AFB828EBDBFFCDA940D3FFCDA94018DF"
The notes played by each key need further tuning, which can be done by changing the DELAY VALUES in the table (first 39 bytes). It appears very feasible, I can get them within a few cents by adjusting the values. Also note that on machines with 60hz display (USA ZX81) the tuning is slightly different, but not by much, perhaps because the program runs in FAST mode with the display turned off

I checked the note frequency with a cheap handheld tuner, which worked pretty well but sometimes picked the wrong octave. Maybe because of the square wave sound overtones (this tuner worked better with a guitar)

Code: Select all

;  10 REM  @ $4082
; machine code (M/L) source: A$ from the BASIC program    
; equivalent assembly:

;39 byte DELAY VALUE table mirroring the structure (keys Z-B) of the ROM KEY table at $007E
;table @ $4082-0073=4004 offset
;          DELAY VALUE      address          KEY  NOTE played [needs further tuning]
table:       db $9B        ;4082 (007E+4004) 'Z'  C 5+ 3.9c ;with DF correction at end of this listing
             db $89        ;4083 (007F+4004) 'X'  D 5-33.6c
             db $73        ;4084 (0080+4004) 'C'  E 5 -9.7c
             db $69        ;4085 (0081+4004) 'V'  F 5 -3.1c
             db $00        ;4086 (0082+4004) 'A'  --
             db $93        ;4087 (0083+4004) 'S'  C#5-30.3c
             db $7E        ;4088 (0084+4004) 'D'  D#5-29.9c
             db $00        ;4089 (0085+4004) 'F'  --
             db $5E        ;408A (0086+4004) 'G'  F#5-23.3c
             db $00        ;408B (0087+4004) 'Q'  --
             db $3A        ;408C (0088+4004) 'W'  C 6-20.3c
             db $30        ;408D (0089+4004) 'E'  D 6-49.1c
             db $26        ;408E (008A+4004) 'R'  E 6-37.0c
             db $24        ;408F (008B+4004) 'T'  F 6     
             db $00        ;4090 (008C+4004) '1'  --      
             db $00        ;4091 (008D+4004) '2'  --      
             db $36        ;4092 (008E+4004) '3'  C#6     
             db $2C        ;4093 (008F+4004) '4'  D#6     
             db $00        ;4094 (0090+4004) '5'  --      
             db $00        ;4095 (0091+4004) '0'  --      
             db $00        ;4096 (0092+4004) '9'  --      
             db $0F        ;4097 (0093+4004) '8'  A#6     
             db $16        ;4098 (0094+4004) '7'  G#6     
             db $1E        ;4099 (0095+4004) '6'  F#6     
             db $BB        ;409A (0096+4004) 'P' --       
             db $0A        ;409B (0097+4004) 'O'  C 7     
             db $0C        ;409C (0098+4004) 'I'  B 6     
             db $12        ;409D (0099+4004) 'U'  A 6     
             db $1A        ;409E (009A+4004) 'Y'  G 6     
             db $00        ;409F (009B+4004) N/L  --
             db $00        ;40A0 (009C+4004) 'L'  --      
             db $00        ;40A1 (009D+4004) 'K'  --      
             db $41        ;40A2 (009E+4004) 'J'  A#5     
             db $4C        ;40A3 (009F+4004) 'H'  G#5 +9.4c
             db $00        ;40A4 (00A0+4004) ' '  --      
             db $38        ;40A5 (00A1+4004) '.'  C 6-44.7c
             db $3e        ;40A6 (00A2+4004) 'M'  B 6-28.4c
             db $46        ;40A7 (00A3+4004) 'N'  A 5 +1.9c
             db $53        ;40A8 (00A4+4004) 'B'  G 5 +0.6c

DELAYB:      LD      A,B                     ;This delay determine the half-cycle of the audio pulse
loopB:       DEC     A
             JR      NZ,loopB
             RET     

;  20 RAND USR 16558 //  #entry/$40AE
entry:       CALL    $02BB                   ;KEYBOARD ROM routine; out:HL=keystates
             LD      B,H                     ;BC=keystates
             LD      C,L
check4key:   LD      D,C
             INC     D
             JR      Z,entry                 ;loop until a key is pressed
             CALL    $07BD                   ;DECODE ROM routine; in:BC=keystates, out:HL=position in ROM KEY table and (HL)=character
             LD      DE,4004H                ;offset
             ADD     HL,DE                   ;HL=position in KEY table. E.g. 'C' 0082+4004=4086
             LD      B,(HL)                  ;load B from DELAY VALUE table
             XOR     A                       ;zero the A register
             CP      B                       ;is B zero?
             JR      Z,entry
             IN      A,($FF)
             CALL    DELAYB                  ;E.g. with $BB delay, time to next half cycle=3013 T-cycles (useconds = 3.25/4,000,000)
             OUT     ($FF),A                 ; NOTE: A440 standard should be 2273 useconds
             CALL    DELAYB                  ; time to next full cycle=7254 T-cycles (2361 useconds, -4% tuning difference, may differ by individual machine)
             JR      entry                   ;18DF corrected from listing (which was entry+1 18E0)
Post Reply