ZX Forum #04
19 ноября 1997 |
|
world of sound Spectrum - Chapter 6.2: Programming effects and music under the musical coprocessor AY- 3-8910 (AY-3-8912).
6.2. Programming All sound effects and music programmed by the constant change of values registers with appropriate delays. Realize this may, for example, such a subroutine: 1415. 10 LD HL, 60000; HL = address of data 20 LOOP LD A, (HL); A = data bytes 30 INC HL; HL = HL +1 40 CP 255; A = 255? 50 RET Z; if so, return 60 CP 16; A = 16? 70 JR NZ, REG; if not, go to the REG 80 LD B, (HL); B = pause duration 90 PAUSE HALT; interrupt latency 100 DJNZ PAUSE; cycle 110 JR CONT; go to the CONT 120 REG LD BC, 65533; BC = port address register 130 OUT (C), A; write register number 140 LD B, 191; BC = address data port 150 LD A, (HL); A = register value 160 OUT (C), A; write data to register 170 CONT INC HL; HL = HL +1 180 JR LOOP; go to top 2 This software is quite primitive, and to play the music does not really fit, but to create simple effects - in most times. Before its launch do not forget prepare a data block at 60000, consisting of pairs of data and ending number 255. The first value in each pair must be a register number and the second - number to be written in the register. In addition, if the first value equals 16, the second is interpreted as delay (in the fifties of a second). For music, use much more complex routines like usually employed in the second interrupt mode. Data for these routines are usually stored in a much more comfortable form separately for each of the three channels. Result in completely even the simplest example of such routines in this book is not possible because of its complexity, but if you are familiar with assembler, you should not write anything a routine, and I can tell, how to do it. First, consider the format of the data. I propose the following system: a melody will be given three (the number of votes) the basic building blocks of data. Since practically any melody consists of identical fragments repeated in different orders, it would be logical in the main unit itself does not define a melody, and the addresses of such fragments. These fragments are usually called patterns (pattern - a stencil, template). So, in the main unit may contain the following byte values: 65,535 (# FFFF) - end of melodies 0 (# 0000) - the beginning of the cycle addr (# XXXX) - address of the next pattern Code "start cycle" (0) marks the spot from which begins playing the melody with repetition. Now for patterns. Without going into the theory, give me developed Format: 128 (# 80) - end of pattern 129, n (# 81, # XX) - set the duration of n 130, n (# 82, # XX) - noise with a frequency of n (0 ... 31) 131, n1, n2 (# 83, # XX, # XX) - noise with a frequency of n (0 ... 31) + note (0 ... 100) 132, n1, n2 (# 84, # XX, # XX) - a direct frequency reference tone (0 ... 4095) 133, addr (# 85, # XXXX) - a task unit frequency change tone 134, addr (# 86, # XXXX) - a task unit frequency change noise 135, addr (# 87, # XXXX) - a task block changes Volume 136, n1, n2, n3 (# 88, # XX, # XXXX) - generator control envelope 0 ... 100 (# 00 ... # 64) - Notes from the LA subkontroktavy Let me explain some of the codes: 129 - As you probably noticed, when a Denmark notes its duration does not indicate is called. The fact that it uses Xia duration, set wages it with this command. Length sensitivity is measured in the Fifties fractions of seconds. 131 - With this code, you may one simultaneously reproduce the tone and noise. 133,134,135 - These codes specify additional blocks of data are positive, indicating how to change the tone frequency, time quency noise and the volume for Playing music. If, after the code 133 or 134 instead of the address block is Xia 0, then change the frequency off Xia. A number from 0 to 15 after the code 135 indicates the need for maintaining of constant volume, corresponding to this number. 136 - This code controls the generator envelope envelope. After him, should we find ditsya-byte integer from 0 to 7, indicating the shape of the envelope in According to Table 5 and dvuhbay tovoe number specifying the period of change of the envelope. 0 ... 100 - These codes define notes. Code 0 corresponds to the note LA subkontrokta you, 1 - LA # 2 - SR, etc. The unit, which describes the change in frequency tone, use the following values: 128 (# 80) - end of block -127 ... 127 (# 81 ... # 79) - the frequency shift Block frequency noise will be given in the following format: 128 (# 80) - end of block -31 ... 31 (# E1 ... # 1F) - the frequency shift A unit volume changes let defined as follows: 128 (# 80) - end of block 0 ... 15 (# 00 ... # 0F) - meaning the volume It is quite logical to make this procedure works in the second interrupt mode. Based on this, as well as from the proposed format of the data, we can see that for each channel will need an array of variables. I suggest the following format: offset size value 0 2 start address of the main block of data February 2 current address in the main block of data February 4 starting block address changes tone frequency June 2 current address in the block frequency tone Aug. 2 starting address block frequency noise February 10 current address in the block frequency noise Feb. 12 start address unit volume changes February 14 current address in the block volume changes February 16 current address in the current pattern 18 January value of the current duration January 19 meter length January 20 the number of remaining repetitions In addition, it will take another three bytes for each channel for storing tempo count rate and the flag resolution sound. The package will include the following Procedure: SINIT - Initializing tables, connection second mode interrupts. SSTOP - Off coprocessor, restore resistivity standard mode interrupt vany. SNEW - Run all three channels. If you call of this subroutine in Regis fuck HL, DE and BC should be Adre sa major blocks of data for the channel crystals A, B and C, respectively. As a result Giustra A should be the number of repetitions tunes from 1 to 254 or 255 if you want to chalk Diya was repeated endlessly. SNEWA - Starting channel A. In the register HL should be addressed to the data block and in case A - the number of repetitions (Similarly SNEW). Working channels B and C, this procedure without affecting em. SNEWB - Starting channel B. All the same SNEWA. SNEWC - Starting channel C. All the same SNEWA. MUTE - ban / permit work. In Regis A triangle should be the channel number of 0 to 2 or 3, if you are applying to all channels. In case B USD wives to be code modes: 0 - stop, 1 - noiseless, 2 - playing. STATUS - Getting the state of the channel. As a result Giustra A should be the channel number from 0 to 2. On return from space A procedure STATUS register contains code mode selected channel la (similar to B in MUTE). TEMPO - Setting the pace. In case A USD wives to be the channel number from 0 to 2 or 3, if you are applying to all channels. In case B should we find ditsya tempo. Thus, the beginning of the package might look like: 1415. 10 ORG 60000 20 JP SINIT 30 JP SSTOP 40 JP SNEW 50 JP SNEWA 60 JP SNEWB 70 JP SNEWC 80 JP MUTE 90 JP STATUS 2 TEMPO procedure might look like: 1415. 100 TEMPO DI 110 PUSH HL 120 PUSH AF 130 LD HL, TEMPS; HL = pointer to the pace 140 CP A, 3 150 JR Z, TEMP3 160 ADD A, L 170 LD L, A 180 JR NC, TEMP1 190 INC H 200 TEMP1 LD (HL), B 210 INC HL 220 INC HL 230 INC HL 240 LD (HL), B 250 TEMP2 POP AF 260 POP HL 270 EI 280 RET 290 TEMP3 PUSH DE 300 LD D, 6 310 TEMP4 LD (HL), B 320 INC HL 330 DEC D 340 JR NZ, TEMP4 350 POP DE 360 JR TEMP2 2 Since I went to data access, it is necessary result in line with their description: 1415. 370 CHAN_A DEFS 21; array of variables for channel A 380 CHAN_B DEFS 21; array of variables for channel B 390 CHAN_C DEFS 21; array of variables for the channel C 400 MUTS DEFS 3; flags permit sound 410 TEMPS DEFS 3; rate 420 CURTS DEFS 3; counters rates 430 AYREGS DEFS 14; copies of registers of a coprocessor 440 ENVS DEFB 0,4,11,13,8,12,14,10; the envelope 450 SVOLS DEFW # 8000, # 8001, # 8002; table changes 460 DEFW # 8003, # 8004 # 8005; of volume 470 DEFW # 8006, # 8007, # 8008; standard 480 DEFW # 8009, # 800A, # 800B; values 490 DEFW # 800C, # 800D, # 800E 500 DEFW # 800F 510 NOTES DEFW ... ; Here to write all the values ; Of Table 9 from the upper left ; Angle in order from top - down, which is valid ; Islands - left 2 Line 430 contains the domain data that is used for audio output. First, it formed the values of all registers of a coprocessor with the following subprograms: 1415. 520 SETAY PUSH HL 530 PUSH AF 540 LD AL, AYREGS 550 ADD A, L 560 LD L, A 570 JR NC, SETAY1 580 INC HL 590 SETAY1 LD (HL), B 600 POP AF 610 POP HL 620 RET 2 She needed to pass the register number in A and its value in B. The contents of this field is copied in real coprocessor registers another subroutine: 1415. 630 AYOUT PUSH HL 640 PUSH DE 650 PUSH BC 660 LD HL, AYREGS +13 670 LD D, 13 680 AYOUT1 LD BC, 65533 690 OUT (C), D 700 LD B, 191 710 LD E, (HL) 720 OUT (C), E 730 DEC HL 740 DEC D 750 JP P, AYOUT1; if D> = 0, then go to AYOUT1 760 POP BC 770 POP DE 780 POP HL 790 RET 2 Any of the registers in this area also read: 1415. 800 GETAY PUSH HL 810 PUSH AF 820 LD HL, AYREGS 830 ADD A, L 840 LD L, A 850 JR NC, GETAY1 860 INC H 870 GETAY1 LD B, (HL) 880 POP AF 890 POP HL 900 RET 2 This routine must pass number required to register A and she will return it value B. Line 440 needed to decrypt package envelope. If any number of tables 5 added to the label ENVS and upon receipt of the address read one byte, you get a value that should be written in R13. Line 450 will need to decrypt standard volume levels. For this be a number from 0 to 15 multiplied by 2 (you can use the SLA) and add to label SVOLS. The value obtained should be used as the address block change the volume. Line 510 will be useful for deciphering the music. If the code notes (from 0 to 100) multiplied by 2 (team SLA) and added to the label of NOTES, and on the resulting address is considered two-byte number, you get the value junior and senior registers frequency. Now for the main procedures: 1415. 910 STATUS PUSH HL 920 LD HL, MUTS 930 ADD A, L 940 LD L, A 950 JR NC, STAT1 960 INC H 970 STAT1 LD A, (HL) 980 POP HL 990 RET 2 This small but useful procedure help the programmer to know in what state is this or that channel. For example, to find which of them is free. The following procedure - MUTE: 1415. 1000 MUTE DI 1010 PUSH HL 1020 PUSH AF 1030 LD HL, MUTS 1040 CP A, 3 1050 JR Z, MUT2 1060 ADD A, L 1070 LD L, A 1080 JR NC, MUT1 1090 INC H 1100 MUT1 LD (HL), B 1110 POP AF 1120 POP HL 1130 EI 1140 RET 1150 MUT2 LD (HL), B 1160 INC HL 1170 LD (HL), B 1180 INC HL 1190 JR MUT1 2 This procedure is necessary, for example, to temporarily stop the work of one of channels. Now - the initialization of channels: 1415. 1200 SNEWC PUSH IX 1210 LD IX, CHAN_C 1220 PUSH BC 1230 LD B, 2 1240 JR SNEW1 1250 SNEWB PUSH IX 1260 LD IX, CHAN_B 1270 PUSH BC 1280 LD B, 1 1290 JR SNEW1 1300 SNEWA PUSH IX 1310 LD IX, CHAN_A 1320 PUSH BC 1330 LD B, 0 1340 SNEW1 DI 1350 PUSH BC 1360 PUSH DE 1370 PUSH HL 1380 PUSH IX 1390 POP HL 1400 PUSH HL 1410 POP DE 1420 INC DE 1430 LD BC, 20 1440 LD (HL), B 1450 LDIR 1460 POP HL 1470 PUSH HL 1480 LD (IX +20), A 1490 LD (IX +0), L 1500 LD (IX +1), H 1510 LD (IX +19), 0 1520 LD E, (HL) 1530 INC HL 1540 LD D, (HL) 1550 INC HL 1560 LD (IX +2), L 1570 LD (IX +3), H 1580 LD (IX +16), E 1590 LD (IX +17), D 1600 LD HL, SVOLS +30 1610 LD (IX +12), L 1620 LD (IX +13), H 1630 LD (IX +14), L 1640 LD (IX +15), H 1650 LD (IX +18), 13; the duration of the default = 1 / 4 1660 POP HL 1670 POP DE 1680 POP BC 1690 LD A, B 1700 LD B, 2 1710 CALL MUTE 1720 LD B, 1 1730 CALL TEMPO 1740 POP BC 1750 POP IX 1760 EI 1770 RET 2 And finally, initialize all three channels: 1415. 1780 SNEW PUSH HL 1790 CALL SNEWA 1800 PUSH DE 1810 POP HL 1820 CALL SNEWB 1830 PUSH BC 1840 POP HL 1850 CALL SNEWC 1860 POP HL 1870 RET 2 Initialization routines to prepare the arrays of variables necessary for the data. They set block addresses frequency tones and noise in the "not used" (will wear they 0). Choose a constant level volume (15). And also set the duration of notes by default equal to 1 / 4 seconds. That routine connect a second Interrupt mode: 1415. 1880 SINIT LD A, 24 1890 LD (65535), A 1900 LD A, 195 1910 LD (65524), A 1920 LD HL, INTR; HL = address of handler 1930 LD (65525), HL 1940 LD HL, 65024 1950 LD DE, 65025 1960 LD BC, 256 1970 LD (HL), 255 1980 LD A, H 1990 LDIR 2000 DI 2010 LD I, A 2020 IM 2 2030 LD HL, MUTS; ban 2040 XOR A 2050 LD (HL), A; work 2060 INC HL 2070 LD (HL), A; all 2080 INC HL 2090 LD (HL), A; channels 2100 EI 2110 RET 2 This subroutine returns the standard mode interrupts on and off coprocessor: 1415. 2120 SSTOP DI 2130 LD A, 63 2140 LD I, A 2150 IM 1 2160 EI 2170 LD HL, AYREGS 2180 LD DE, AYREGS +1 2190 LD BC, 13 2200 LD (HL), B; B = 0 2210 LDIR; cleaning of registers 2220 LD A, 7 2230 DEC B; B = 255 2240 CALL SETAY; R7 = 255 (off mixer) 2250 JP AYOUT; output registers in the coprocessor 2 Now let us interrupt handler. Since he must serve three channels, and arrays of variables is most easily addressed registers IX, we can propose this routine: 1415. 2260 INTR PUSH AF; preservation registers 2270 PUSH HL 2280 PUSH DE 2290 PUSH BC 2300 PUSH IX 2310 LD IX, CHAN_A; training registers 2320 XOR A 2330 CALL DISPAT; coprocessor 2340 LD IX, CHAN_B 2350 LD A, 1 for all channels 2360 CALL DISPAT 2370 LD IX, CHAN_C 2380 LD A, 2 2390 CALL DISPAT 2400 CALL AYOUT; output registers in the coprocessor 2410 POP IX; restore registers 2420 POP BC 2430 POP DE 2440 POP HL 2450 POP AF 2460 RST 56; standard call handler 2470 RET 2 This handler for each channel calls the dispatcher (DISPAT), holding up to register A channel number, and register IX - the array address of its variables. Role DISPAT procedure is to process variables TEMPS, CURTS and MUTS for specified channel, as well as to call the main subroutine creation of sound - GETSND. Here is the text of procedure DISPAT: 1415. 2480 DISPAT PUSH AF 2490 LD E, A 2500 LD D, 0 2510 CALL STATUS 2520 OR A; channel stopped? 2530 JR NZ, DISP1 2540 POP AF 2550 LD B, A 2560 JR DISP3 2570 DISP1 LD HL, CURTS 2580 ADD HL, DE 2590 LD A, (HL) 2600 OR A 2610 JR Z, DISP2 2620 DEC (HL); reduction in the rate meter 2630 POP AF 2640 RET 2650 DISP2 DEC HL; update 2660 DEC HL 2670 DEC HL; counter 2680 LD A, (HL) 2690 INC HL; rate 2700 INC HL 2710 INC HL 2720 LD (HL), A 2730 POP AF 2740 CALL GETSND; challenge the basic procedure 2750 LD B, A 2760 CALL STATUS 2770 CP 1; should "drown out"? 2780 RET NZ 2790 DISP3 LD C, B; "mute" 2800 LD HL, AYREGS +6 2810 LD A, 9; channel 2820 DISP4 SLA A 2830 DJNZ DISP4 2840 OR (HL) 2850 LD (HL), A 2860 INC HL 2870 ADD HL, BC 2880 LD (HL), 0 2890 RET 2 So, all service procedures are given. Only one left - GETSND: 1415. 2900 GETSND ... 2 That is what I propose to write to you. But do not worry - I'll explain everything in detail. Most likely, the procedure will GETSND is sufficiently large. Perhaps even more of all these procedures together. But there is nothing difficult in it does not, and its volume due to the rather complex format data. The task procedure GETSND reduces the formation of certain cells of AYREGS data of one channel for subsequent copying into registers coprocessor. The details of this procedure transferred to the channel number in register A (that she knew of any place cells data for the frequency, volume, etc.) and address of an array of variables in the register IX. Note that it is obliged to preserve the value of the register A! You may even have to make an additional variable to store it. Thus, the procedure in the procedure GETSND the following: 1. Check if there is zero counter duration (IX +19). 2. If not, then continue playback of the current note. 3. If equal, then select a new note and start its playback. The term "resume playback current notes "includes the following: 1. Reduce the length of the counter. 2. If the address of one of the additional blocks is 0, items 3 ... 5 for this unit perform is not necessary. 3. Choose the next value of the blocks Frequency and volume, using Using variables IX +6 / IX +7, IX +10 / IX +11 and IX +14 / IX +15. 4. In accordance with the selected values mi and the channel number with the update on the aid procedures and GETAY SETAY Region AYREGS (note that the bias the frequencies may be negative mi). 5. Update variables to addresses IX +6 / IX +7, IX +10 / IX +11 and IX +14 / IX +15 in with correspondence with paragraph 3. Start playback of music "includes in itself is only one item: 1. Rewrite the variables to addresses IX +4 / IX +5, IX +8 / IX +9, IX +12 / IX +13 and IX +18 in their counters - doubles (IX +6 / IX +7, IX +10 / IX +11, IX +14 / IX +15 and IX +19). But the point to choose a new note - a little more complicated: 1. Choose the next byte from the current pattern (e - IX +16 / IX +17). 2. If it is not equal to 0 ... 100, 130, 131 and 132 - treat as appropriate control code and go to Step 1. 3. Accordingly, a byte or a couple meters and the channel number of the update AYREGS region and a variable IX +16 / IX +17. Now, the processing control codes: Code 128: 1. Choose the address of the next pattern of the main unit (addressed mostly to block Ke contained in IX +2 / IX +3). 2. Update variable IX +2 / IX +3. 3. If the address pattern is zero, Skopje rovat variable IX +2 / IX +3 in IX +0 / IX + 1 and go to Step 1. 4. If the address is 65535, copy variable IX +0 / IX +1 in IX +2 / IX +3 and reduce the repeat count (IX +20). If the repeat count is zero, set the channel state to stop Flax "by the procedure of MUTE. Continue to step 1. 5. Record the selected address in IX +16 / IX +17 and select a new note. " Code 129: 1. Get byte, followed by this code, and recorded in the IX +18. Select a new note. " Code 133 (134): 1. Get address, followed by this code, and put it in the IX +4 / IX +5 (IX +8 / IX + 9). Select a new note. " Code 135: 1. Get address, followed by this code. 2. If it is less than 16, calculate the corresponding corresponding address in the table SVOLS. 3. Put the probe in IX +12 / IX + 13. 4. Select a new note. " Code 136: 1. Set in the register of the volume set of the channel to 16. 2. Write to IX +14 / IX +15 zero. 3. Get byte, followed by this code. 4. Calculate the table ENVS value R13 and renew the domain AYREGS. 5. Take the two bytes following the code forms and bring them into the cells 11 and 12 area AYREGS. 6. Select a new note. " Now how can calculate the number of registers for a given channel. To calculate the number of the register of frequency, rather channel number multiplied by 2 (ADD A, A). Resulting number is the number register Low Byte frequency. To get the register number of the byte in the frequency, the value should be increased by 1 (INC A). To calculate the volume number of the register, it is necessary to add the channel number 8 (ADD A, 8). If you write a procedure GETSND, in Your hands will be quite a powerful program, suitable for writing both music and effects. And at the end of the description of this program - tips on compiling the data blocks for her. To raise or lower the note one octave, its value must be correspondingly increased or decreased by 12. Note BEFORE the first octave corresponds to the number 39. The values of the durations you can take Table 11. Now, some tips on programming a coprocessor. For the formation of new sounds you can use the generator envelope that is configured to periodically change the volume and greater frequency. Particularly good results can be achieved by configuring it at multiples frequency of the main signal. To mute the music co-processor is often used prohibition all functions of the mixer (output byte 255 R7), but this method is not very reliable. If the envelope generator is configured to periodically change the volume, then this the trick will not work: will be audible click. For a complete silencing of a coprocessor can recommend a routine: 1415. 10 LD HL, DATA; HL = address of data 20 LD E, 10; E = number of first register 30 LOOP LD BC, 65533; BC = port address register 40 OUT (C), E; output port E in BC 50 LD A, (HL); A = value of the next Register 60 LD B, 191; BC = address data port 70 OUT (C), A; output to port A BC 80 INC HL; HL = HL +1 90 DEC E; E = E-1 100 LD A, E; E = 110 CP; 6 6? 120 JR NZ, LOOP; if not, then the cycle 130 RET; Returns 140 DATA DEFB 0,0,0,255; data registers AY 2 In many cases, required to determine whether there is a coprocessor to the computer. Some do it by checking the type of computer (48K/128K), but this method does not quite fair, since AY can stand and the good old Spectrum. Here is a subroutine, which determines the presence of a coprocessor more reliably: 1415. 10 LD BC, 65533; BC = port address register 20 XOR A; A = 0 30 OUT (C), A; selection register 0 40 LD B, 191; BC = address data port 50 OUT (C), A; output 0 in the selected case 60 LD B, 255; BC = port address register 70 IN A, (C); input values from the selected Register 80 OR A; A = 0? 90 RET; Returns 2 If after calling this subroutine Z flag is cleared, then the coprocessor is present. Otherwise - no. And finally I want to tell you about one very interesting technique. It is often used in many programs. Reading data from the registers are up and converting them appropriately in graphical information along with music playback, you can make soundlights or peak signal level.
Other articles:
Similar articles:
В этот день... 21 November