Authors
Publication
Publication Details
Volume: 3 Issue: 6
Date
Pages
Digitally Encoded FM Audio Generator — is a 29 byte machine code routine that allows you to store audio frequency data and to synthesize the facsimile sound at will. You may use complex mathmatical formulas to provide digitally sampled values from any continuous number field. These values are correlated to the audio spectrum so you can “hear” the resultant waveform. One version of the DEFMAG driver uses a single byte of the data storage area to hold the value from an individual key pressed. It turns the keyboard into a crude electronic organ.
The synthesized sound can be played through the TV audio system simply by turning up the TV volume control and adjusting the fine tuning for optimum sound. Better fidelity can usually be obtained from the mic output from the computer. Make the mic-to-mic connection between your ZX/TS computer and your recorder in the usual way. The sound generated by DEFMAG may be recorded onto tape, monitored by an earphone plugged into the cassette ear jack or amplified though some other high impedance input.
DEFMAG Programming Instructions
The frequency data storage area of this routine must be able to contain zero or any positive integer up to 255 that can be POKEd in. Since certain values such as 118, 126, and 127 cause problems in LISTing, DEFMAG cannot be stored in an ordinary REM statement. Instead we will load the DEFMAG machine code and set up the frequency data storage area in an unlisted REM statement located between the listed program and the display file. This requires unique USR calls referenced to the display file (the variable F).
The programming steps are as follows:
1) Create a REM sttement to hold 256 data bytes and 29 machine code bytes. Type in the REM filler program in Listing 1. To use the REM filler, in FAST mode, EDIT line 50 and key in a series of Xs as efficiently as you can. When you think you have depressed the X key a total of 280 times, press RUN and ENTER. The screen prompt will tell you how many Xs to add or delete to be correct. When the REM statement needs 0 characters, the command in line 30 will automatically isolate this area from the rest of the LISTed program, and the REM line will not be displayed on the screen. The screen should now look like Listing 2.
2) Delete the remaining lines of the REM filler by entering each line number and ENTER. Be sure not to use NEW or you will wipe out the storage area.
3) Type in Listing 3, the machine code loader program.
4) Hit RUN and ENTER. In response to the L cursor enter the first number in the machine code table in Figure 1 and press ENTER. Continue entering the numbers (left to right) pressing ENTER after each. When all are entered, delete the lines of the loader program by typing each line number and hitting ENTER. Do not use NEW or you will erase the code. It is a good idea to SAVE the program at this point.
5) Type in the Driver program of your choice (A, B, C, D).
You are now ready to try the program.
DEFMAG Operating Theory
Since DEFMAG resides immediately below the display file, its address moves around as changes are made in the program listing. The only way to track DEFMAG USR addresses is by their relationship to the display file (-F). If any address is incorrect by just one byte the entire system can go haywire. The value of F must be updated as program changes are made.
A call to USR (F-29) loads the HL register pair with the address of the first byte of frequency data (F-285). The contents of that byte are tested to see if it contains the “stop code” 255. If the stop code at (F-30) or code 255 located anywhere else in the data field is encountered, the MC routine returns to Basic.
If the stop code is not encountered then register B is loaded with “duration” data that has been POKEd in. Register B is actually used to count down the number of cycles of the given frequency.
Next the output is turned on and a delay is begun that determines the period of the high logic half cycle as specified by the frequency data byte. When the delay is complete the output is turned off for a delay time also determined by the data byte. This series of on-off pulses recycles until register B counts down to zero. Then HL is incremented to the next data byte and the process repeats.
There is an anomaly in this type of synthesis. Since each tone that is generated has the same number of cycles, higher frequencies will have a tone of shorter duration since the period is shorter at those frequencies. Some important addresses to know are:
First frequency data byte: (F-285)
Stop code: (F-30)
USR address: (F-29)
Location of first byte (lsb): (F-28)
Location of first byte (msb): (F-27)
Duration: (F-21)
In normal operation the address of the first frequency data byte is POKEd into (F-28) and (F-27) and a duration value — usually a small number — is POKEd into (F-21). You can imagine the monotonous sound a string of X’s (data 61) would make if synthesized so the rest of this article is devoted to filling the frequency data field with meaningful numbers.
DEFMAG Operating Instructions
Whether you use driver A, B, or C, the data encoding procedure is the same. Line 60 of each program applies a formula to the values of I from to 254 to yield a set of numbers ranging in value (but not in sequence) from to 254. Some test formulas are shown in Figure 3 that can be substituted for line 60 in driver program A, B or C.
If you like to work with math, Figures 4 and 5 will enable you to test any formula before applying it. In Figure 4 the formula goes in line 30 and is assigned to the variable A instead of using the POKE command from driver line 60. The plotted waveform is shown.
It is also possible to plot multiple waveforms using this technique. Figure 5 demonstrates the procedure with the composite waveform. Figure 6 shows how the same formulas are integrated into driver program A.
Figure 7 displays the entire data field generated by any formula. This allows scaling the formula so that it provides positive integers within the proper range. Given I, the set of integers from 0 to 254, and the formula in line 40, the numbers shown in Figure 7 would result. The number of lines is too great to fit on the screen at one time so you will have to use CONT to view the second part of the data field.
Driver Programs
Let us now discuss the specific operation and differences in the driver programs. Enter RUN to operate any of the four drivers. After a brief programming cycle where waveform data is POKEd into the storage area in A and C, the screen prompt asks, “Enter Duration’ 1.
After entering a value, the sound will be generated (with driver B it is automatic). Driver A operates continuously much like a siren until the loop is exited by pressing BREAK. Driver B operates continuously but with a pseudo-random duration. Driver C plays the tone sequence each time any key except BREAK is pressed.
Driver D operates quite differently from the others. This program responds to any key pressed (except BREAK, SHIFT, [period], and ENTER) by giving a tone. The notes ascend in pitch from 0,1,2,3 . . . 7,8,9,A,B,C … X, Y,Z although they are not very evenly tempered. You may experiment with line 90 to improve the pitch. For a repeating trigger, delete lines 110 and 120 and change line 130 to read GOTO 50.
Listing 1 . REM filler program
10 LET A=282\n20 LET B=PEEK 16642+256*PEEK 16643\n30 IF A-B=0 THEN POKE 16640,118\n40 PRINT "REM NEEDS ";A-B;" BYTES"\n50 REM XXXX
Listing 2. REM line complete
10 LET A=282\n20 LET B=PEEK 16642+256*PEEK 16643\n30 IF A-B=0 THEN POKE 16640,118\n40 PRINT "REM NEEDS ";A-B;" BYTES"
Listing 3. MC loader program before loading MC
10 LET F=PEEK 16396+256*PEEK 16397\n20 DIM A$(29,4)\n30 FOR I=1 TO 29\n40 INPUT A$(I)\n50 PRINT A$(I)\n60 POKE F+(I-31),VAL A$(I)\n70 NEXT I
Figure 1. Machine code table
255 33 0 0 126 254 255 200\n6 0 211 255 94 28 29 32\n253 219 254 28 123 190 32 251\n16 240 35 24 231
Figure 2. DEFMAG disassembly
The value of F
-30 STOP CODE,255
-29 LD HL, address of first storage byte
-26 LD A,(H) ;test for
-25 CP,255 ;stop code
-23 RET Z
-22 LD B, duration
-20 OUT 255,A ;turn on output
-18 LD E,(HL)
-17 INC E
-16 DEC E
-15 JR NZ,-16
-13 IN A,254 ;turn off output
-11 INC E
-10 LD A,E
-9 CP (HL)
-8 JR NZ,-11
-6 DJNZ,-20 ;jump to begin next cycle
-4 INC HL ;move counter to next data byte
-3 JR -26 ;start over with new data byte