ZX Forum #04
19 ноября 1997 |
|
world of sound Spectrum - chapter 4.6: Treatment of external signals - digitization.
4.6. Processing of external signals ZX-Spectrum provides programmers an interesting opportunity - to read and memorize the sound signals fed to its input tape. These fragments can be played at different speeds, which is undoubtedly very interesting. True, the quality of the received so the sound leaves much to be desired, and its maximum duration limited to a few tens of seconds (simply running out of 48K of RAM!) But the move from words to deeds. That routine, record sounds in memory: 1415. 10 DI; ban interrupt 20 LD HL, 25000; HL = address of save sound 30 LD DE, 35000; DE = duration of sound 40 LOOP1 LD B, 8; B = bit counter 50 LOOP2 SLA (HL); scrolling the values in memory 60 IN A, (254), enter the value from port 254 70 BIT 6, A; check bit recorder 80 JR Z, NOSIGN; if 0, then go to NOSIGN 90 SET 0, (HL); set bit D0 in the memory 100 NOSIGN LD C, 3; C = delay 110 PAUSE DEC C; C = C-1 120 JR NZ, PAUSE; if C <> 0 then loop 130 DJNZ LOOP2; continue the loop Byte 140 INC HL; HL = HL +1 150 DEC DE; DE = DE-1 160 LD A, D; DE = 170 OR E; 0? 180 JR NZ, LOOP1; if not, then the cycle 190 EI; permission to interrupt 200 RET; Returns 2 This routine play: 1415. 10 DI; ban interrupt 20 LD HL, 25000; HL = address of the stored audio 30 LD DE, 35000; DE = duration of sound 40 NOP; reserve 50 XOR A; A = border color (0) 60 LOOP3 LD B, 8; B = bit counter 70 LOOP4 AND 239; reset bits D4 register A 80 RLC (HL); scrolling through the data flag CY 90 JR NC, NOSGN; if the flag CY = 0, then go on NOSGN 100 OR 16; setting bit D4 register A 110 NOSGN OUT (254), A; output to port A 254 120 LD C, 3; C = delay 130 PAUS2 DEC C; C = C-1 140 JR NZ, PAUS2; if C <> 0 then loop 150 DJNZ LOOP4; continue the loop Byte 160 INC HL; HL = HL +1 170 LD C, A; preservation A 180 DEC DE; DE = DE-1 190 LD A, D; DE = 200 OR E; 0? 210 LD A, C; A recovery 220 JR NZ, LOOP3; if DE <> 0 then loop 230 EI; permission to interrupt 240 RET; Returns 2 Data address and length must be the same in these two routines. Please Also note that they use 35 KB of memory from address 25000. Therefore, this area of RAM there should be no data. Own routines, too, should be placed somewhere else. The best option would be: renumber the line second subprogramme from 210 and increments of 10 (if you're in GENS4 - enter the command for this purpose N210, 10); connect what happened to The first subroutine and enter the following lines: 1415. 7 ORG 24900 20 LD HL, BUFFER 30 LD DE, LENGTH 220 LD HL, BUFFER 230 LD DE, LENGTH 450 LENGTH EQU 35000; LENGTH = 35000 460 BUFFER NOP; there is a buffer 2 Make sure also that the assembly was located approximately at the address 40000. In Either way, it will be erased from memory subroutine is called a sound input. Therefore, you should not call it from the doomed assembly. One important note: When using these routines, make sure that BUFFER + LENGTH expression was no longer 65535, another portion of the audio data just is not recorded, but instead you will hear noise. In line 100 the first sub in 120 second row in the register C is stored delay between the sample data. If these two values are equal, then the sound will be played with real pace. If the second number is smaller than the first, the sound will be accelerated, and if more - to slow down. Moreover, the smaller the delay in the input routine, the higher the quality of the input signal, but less than its duration. Bight reserve in routine play is designed for turning sound that is playing it at the end beginning. To enable this effect should be replace operation NOP in this byte to ADD HL, DE, and INC HL on line 160 at DEC HL. There is another way of sound recording. It is based on the calculation of sound pulses. Before the first way he has no special advantages, except for possible slight decrease in noise level. Here are routine, recording the sound of the second method: 1415. 10 DI; ban interrupt 20 LD HL, 25000; HL = address of save sound 30 LD DE, 35000; DE = duration of sound 40 LD BC, 511; C - buffer, B - Counter 50 LOOP1 IN A, (254); input values of port 254 60 EXX; shift register set 70 LD B, 1; B = delay 80 PAUSE DJNZ PAUSE; delay 90 EXX; shift register set 100 BIT 6, A; check bit recorder 110 LD A, 0; A = 0 120 JR NZ, SIGN; if bit D6 = 1, then go at SIGN 130 DEC A; A = 255 140 SIGN CP C; A = C (previous value)? 150 JR NZ, WRITE; if not, go to WRITE 160 INC B; B = B +1 (pulse counter) 170 JR NZ, LOOP1; if B <> 0 then loop 180 WRITE DEC B; B = B-1 190 JR NZ, POKE; if B <> 0 then go to POKE 200 LD B, 2; B = 2 210 CPL; inverting A 220 LD C, A; C = A 230 JR LOOP1; go to LOOP1 240 POKE INC B; B = B +1 250 LD (HL), B; record values in the memory 260 LD B, 1; B = 1 270 LD C, A; C = A 280 INC HL; HL = HL +1 290 DEC DE; DE = DE-1 300 LD A, D; DE = 310 OR E; 0? 320 JR NZ, LOOP1; if not, then the cycle 330 EI; permission to interrupt 340 RET; Returns 2 Line 20 is given the address conservation sound, in line 30 - the duration of the input sound, the line 70 - the delay between samples the signal. Lines 180 - 240 provide noise reduction. The register C value stored previous samples, and register B is the count of identical samples. But the routine play: 1415. 10 DI; ban interrupt 20 LD HL, 25000; HL = address of the stored audio 30 LD DE, 35000; DE = duration of sound 40 NOP; reserve 50 XOR A; A = border color (0) 60 LOOP2 LD B, (HL); B = regular length 70 LOOP3 OUT (254), A; output to port A 254 80 EXX; shift register set 90 LD B, 1; B = delay 100 PAUS2 DJNZ PAUS2; delay 110 EXX; shift register set 120 CALL 124; compensation 130 BIT 0, (HL); delay 140 DJNZ LOOP3; cycle 150 LD B, (HL); B = current duration 160 DEC B; B = 170 INC B; 0? 180 JR Z, CONT; if yes, go to the CONT 190 XOR 16; inverting bits D4 200 CONT INC HL; HL = HL +1 210 DEC DE; DE = DE-1 220 LD B, A; preservation A 230 LD A, D; DE = 240 OR E; 0? 250 LD A, B; A recovery 260 JR NZ, LOOP2; if DE <> 0 then loop 270 EI; permission to interrupt 280 RET; Returns 2 Line 20 is given the address stored audio, line 30 - its duration, On line 90 - a delay between samples (It - playback speed). Bight reserve, as before, is intended to reverse play. For inclusion of this effect must be replaced NOP operation in this byte to ADD HL, DE, and INC HL on line 200 at DEC HL. Lines 120 and 130 are only needed for time synchronization with the routine recording (at 124 is the team RET). Everything has been said about the delay between samples and memory allocation for routines that use the first method record, also holds for sub-programs, using the second method. Feature of the second type sub- is that the duration of the recorded sound depends not only on the amount of dedicated memory, but from the sound. Than smaller differences in the levels of the recorded sound (in other words - less than its average frequency), the longer sound can be recorded. For example, if you write a "silence", the memory is enough for a few minutes! You can arbitrarily change the address and the length of the memorized sound, but need to be very careful not to spoil the vital areas of memory, such as the stack or the system variables BASIC. Sound recorded by these routines can be stored on tape or disk using the normal write commands, and then load as needed. Since not even a very long beep fragment is in memory of a lot of space, there is a natural desire to somehow his cut. I hasten to please you - this is possible! Audio data is very good is compressed by any algorithm. For This can even be used on-screen compressors. It would be their little modified for such use, but if you can not do it, ladies some advice. First, without changing the compressor can compress only those files whose size is less than or equal to 6912 bytes (if any compressor refuses to accept files with a length different from the 6912 b. then supplement them with up to a given size zero). Secondly, the usual compressors to extract images put it right in the area of the screen. Therefore, have the data to move from there to their Native address. This can be done using the following routines: 1415. 10 LD HL, 16384; 20 LD DE, 16385, cleaning 30 LD BC, 6911; 40 LD (HL), L; screen 50 LDIR; 60 CALL DECOMP; call decompressor 70 LD HL, 16384; HL = move from 80 LD DE, ADDR; DE = to move 90 LD BC, LENGTH; BC = how to move 100 LDIR; data movement 110 CALL 3435; subroutine call CLS 120 RET; Returns 2 These will be screened so short time that you most likely this and not notice (at a sufficiently rapid procedure decompression). Finally, the text of the program in Basic, which loads and reproducing sounds with optimal parameters: 10 CLEAR VAL "24899": PRINT "Wait please ..." 20 FOR A = VAL "24900" TO VAL "24972": READ D: POKE A, D: NEXT A 30 CLS: PRINT "Press any key, then speak ...": PAUSE NOT PI 40 CLS: RANDOMIZE USR VAL "24900" 50 CLS: PRINT "Press any key to replay ...": PAUSE NOT PI 60 CLS: RANDOMIZE USR VAL "24934": GOTO VAL "30" 1970 DATA 243,33,141,97,17,114,158,6,8,203,38,219,254,203,119, 40,2,203,198,14,1,13,32,253,16,239,35,27,122,179,32, 231,251,201 1980 DATA 243,33,141,97,17,114,158,0,62,7,6,8,230,239,203,6,48, 2,246,16,211,254,14,1,13,32,253,16,239,35,27,79,122, 179,121,32,229,251,201 If you want to start playing "the opposite," insert into this program the following line: 1945 POKE VAL "24941", VAL "25": POKE VAL "24963", VAL "43" To disable this effect, remove this line and restart the program. Unusual record numbers in this program leads to save memory. Thus, the expression "24900" takes 11 bytes, and "VAL "24900" - only 8 ("NOT PI" equals zero).
Other articles:
Similar articles:
В этот день... 21 November