Thursday, 14 May 2009

Machine Coding 101 (User-Defined Sound)

Featured in the August 2008 issue of Computer Music magazine is an article on lo-fi production in which I give a tip for creating sound on a ZX Spectrum. As it is written in Z80 assembly, I thought this blog might give further enlightenment, and some workable examples in BASIC and machine code. 


Below is a BASIC program written for a ZX Spectrum. It compiles a machine code routine called "uds" which is short for User-Defined Soundreader. Its main purpose is to play sound effects.


The lines beginning with the BASIC command DATA hold the machine code opcodes and data for this routine. 


Lines 530 to 600 are where the sound effect is created. Here this is given as an example, but really any data in any part of the memory will do. The sound stops being read when uds finds a zero.


At line 10 uds is positioned into memory at address 32768 which might seem like a strange number, but it is exactly half way through the total machine memory, and begins to make more sense if viewed as hexadecimal or as higher and lower order bytes in decimal - 128, 0, i.e. 128 * 256 + 0 = 32768. Perhaps this is running before walking. The point being that you can change this number, but I would recommend that if you do, make it higher so that it doesn't clash with any BASIC program. 


Line 20 defines where this particular sound effect is placed in memory, again it could be anywhere, but here its "a bit further on from uds", and the address is called udata.


Line 50 defines the variable "duration" with a default of 1. The sound can be stretched by increasing this number up to a maximum of 255. But it will lose its identity pretty quickly, and I usually don't go beyond 16.


Line 320 contains the number 8. This value I refer to as the inner wheel tuning and it is meant to balance the sound. Again this value can be increased up to 255 to lower the overall tuning.


310 and 440 contain the value 251. It can be changed to a value between and including 244 to 251. I think of this as being an octave ladder. 244 being the lowest. 


After the routine is compiled and the sound effect created, it will be triggered and then pause until you press the keyboard, then triggered again.


Well that's all for now, folks. I'll update this blog with further explanations, examples and links.


10 LET uds = 32768

20 LET udata = uds + 256

30 LET udataH = INT (udata / 256)

40 LET udataL = udata - (256 * udataH)

50 LET duration = 1

60 LET a = uds

70 RESTORE 140

80 READ x

90 IF x = -1 THEN CLS: PRINT a, a - 32768: GOTO 530

100 POKE a, x

110 LET a = a + 1

120 GOTO 80

130 REM _______uds

140 DATA 33, udataL, udataH

150 DATA 175

160 DATA 126

170 DATA 246, 0

180 DATA 32, 1

190 DATA 201

200 DATA 1, duration, 0

210 DATA 197

220 DATA 6, 0 

230 DATA 78

240 DATA 197

250 DATA 62, 16

260 DATA 211, 254

270 DATA 0, 0, 0, 0, 0, 0, 0

280 DATA 11

290 DATA 121

300 DATA 176

310 DATA 32, 251

320 DATA 1, 8, 0

330 DATA 11

340 DATA 121

350 DATA 176

360 DATA 32, 251

370 DATA 62, 7

380 DATA 211, 254

390 DATA 193

400 DATA 0, 0, 0, 0, 0, 0, 0

410 DATA 11

420 DATA 121

430 DATA 176

440 DATA 32, 251

450 DATA 193

460 DATA 11

470 DATA 121

480 DATA 176

490 DATA 32, 204

500 DATA 35

510 DATA 24, 191

520 DATA -1

530 REM ___________udata 

540 LET length = 254

550 FOR n=0 TO length STEP 2

560 LET ang = (n / length)*360

570 POKE udata + n, n + 1

580 POKE udata + n + 1, 128 + 32 * SIN (ang * PI / 45)

590 NEXT n

600 POKE udata + 255, 0

610 REM __________trigger

620 RANDOMIZE USR uds

630 PAUSE 0

640 GOTO 620

2 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Interested in reusing this code. Are you willing to place this code in the public domain?
    Could you contact me?

    ReplyDelete