PARTE 7: FORMA DE ONDA PERSONALIZADA Y REVISADA
Con el fin de acortar la discusión sobre las formas de onda, la última vez se hicieron algunas generalizaciones. Volvamos atrás y maticemos esos comentarios.
Esta es la verdad: las formas de onda personalizadas se pueden usar simultáneamente con otras rutinas. Es más, incluso pueden convivir con rutinas BASIC. ¿Sorprendido? Repasemos los argumentos en contra del uso simultáneo de formas de onda personalizadas.
Teniendo en cuenta esto, sería fácil concluir que no hay manera de producir una forma de onda personalizada utilizable que continúe reproduciéndose durante la ejecución de un programa BASIC. Sin embargo, donde esta línea de pensamiento se desvía es en el supuesto de que la única interrupción que tenemos a nuestra disposición es el espacio en "vertical blank - supresión vertical". Es un error comprensible: las rutinas VB1 se han vuelto tan populares que los programadores ahora cuelgan la mitad de sus códigos en ellas, y una vez que descubrimos un enfoque útil para un problema tendemos a pensar en todos los problemas similares de la misma manera. Sin embargo, hay muchas otras interrupciones disponibles, y una en particular que es tremendamente más flexible que una VBI.
Los Temporizadores De Interrupción Del Pokey. El mismo hardware utilizado para generar efectos de sonido estándar del Atari tiene un truco interesante: cuando los temporizadores Pokey 1, 2 y 4 cuentan regresivamente hasta cero, generan una solicitud de interrupción, lo que hace que el 6502 salte a través de los vectores RAM globales VTIMR1, VTIMR2 o VTIMR4. Las direcciones de estos vectores son $210, $212 y $214 respectivamente. Por lo general, estos vectores simplemente apuntan a una secuencia PLA-RTI, por lo que no sucede nada como resultado de la interrupción.
Sin embargo, cuando uno de estos vectores se cambia para que apunte a una rutina de interrupción, nos proporciona una ingeniosa interrupción controlable por frecuencia para rutinas en las que el tiempo es crítico. Las viejas fórmulas para determinar la frecuencia aún se aplican, por lo que todo lo que tenemos que hacer es determinar con qué frecuencia queremos que se ejecute la rutina, calcular el valor AUDF correspondiente e introducirlo en los registros de frecuencia para ese canal en particular. Ni siquiera tendremos que preocuparnos por recargar el temporizador, Pokey lo recarga automáticamente con el último valor introducido en AUDF.
A veces, la capacidad incorporada en esta máquina simplemente te deja sin aliento.
Generar formas de onda personalizadas simultáneas se vuelve terriblemente fácil cuando se ve desde esta perspectiva. Necesitamos tres rutinas: una para configurar la interrupción (iniciar el sonido), otra para borrar la interrupción (hacer que se calle) y la interrupción en sí, que simplemente seleccionará los valores sucesivos de una tabla de formas de onda y los introducirá en AUDC. Una vez que se ha ejecutado la rutina de configuración, BASIC selecciona la frecuencia de la nota y la introduce en AUDF de la misma manera que hemos estado seleccionando frecuencias todo el tiempo. BASIC puede elegir una nota, irse y hacer algo interesante (El programa de ejemplo dibuja algunos cuadros bonitos) y el sonido no se detendrá hasta que ejecutemos la rutina de silencio.
¿Las limitaciones? Bueno, hay tres. Cuanto mayor sea la frecuencia, más notable será la distorsión causada por DMA, etc. Aún más alto, las interrupciones ocurren tan rápido que la máquina no puede prestar atención a nada más y bloquea el programa en el valor AUDF 2. (Puede recuperarlo presionando la tecla SYSTEM RESET y su programa seguirá intacto).
La tercera limitación es que cuanto mayor sea su frecuencia, menos tiempo de máquina estará disponible para el resto del programa. Por ejemplo, usar el editor de pantalla mientras la interrupción avanza con un valor AUDF 3 es extraño: el sistema operativo se vuelve tan lento que puede ver cada línea individual desplazarse hacia arriba en la pantalla. Evidentemente, este efecto sería bastante inaceptable en un programa.
El Programa De Ejemplo. La demostración BASIC instala las tres rutinas que acabamos de describir y luego las utiliza para reproducir un motivo aplastado de la "Sonata Claro de Luna" de Beethoven mientras dibuja cuadros en la pantalla. Las variaciones de tempo son estrictamente el resultado de los distintos períodos de tiempo necesarios para dibujar los cuadros de diferentes tamaños; ciertamente es posible lograr un tempo constante alterando la rutina de visualización a una de una duración más predecible.
La forma de onda que se reproduce es una onda de rampa (o sierra), que produce un tono nasal bastante diferente al de la onda cuadrada estándar y, sin embargo, lo suficientemente agradable como para usarlo como efecto musical. Las frecuencias utilizadas son bastante bajas, para evitar los problemas descritos anteriormente, pero se pueden utilizar frecuencias más altas que éstas.
Ambos listadoss deberían explicarse por sí solos, pero dos elementos merecen un comentario. Tenga en cuenta que la rutina BASIC tiene cuidado de introducir un valor de frecuencia en AUDF antes de llamar a la rutina de configuración. Esto es para garantizar que AUDF contenga un valor lo suficientemente bajo como para evitar el bloqueo del programa.
También tenga en consideración que la tabla de formas de onda (en el listado Ensamblador) tiene ocho pasos. Acortar o alargar esta tabla aumentará o disminuirá las frecuencias obtenidas por AUDF. Acortar la tabla a cuatro pasos, por ejemplo, produciría sonidos una octava más altos que los creados por la versión actual. Esta es una forma de conseguir tonos más altos sin que el resto del programa se vuelva lento, a expensas de la resolución de la forma de onda. Si cambia la longitud de la tabla, recuerde cambiar la parte del código que envuelve el puntero WINDX de la forma de onda.
Ingrese este programa, use las rutinas en su propio trabajo y esperamos que disfrute tanto usándolas como lo hizo su corresponsal al escribirlas. Esta técnica, y las posibilidades que abre, es uno de esos descubrimientos fortuitos sobre Atari que pueden dejarte emocionado durante días.
Demostración BASIC De Sonido Usando Una Interrupción
0001 REM Interrupt Sound Demo 0002 REM (with apologies to Ludwig) 0003 REM Routine addresses and freq register equate 0004 SET=1536:CLEAR=1558:AUDF=53760 0005 REM Poke in machine language 0006 FOR L=1536 TO 1600 0007 READ BYTE 0008 POKE L,BYTE 0009 NEXT L 0010 REM Data bug check 011 READ BYTE 0012 IF BYTE <>-1 THEN ?"Data error.":STOP 0013 REM Set up graphics 0014 GRAPHICS 23 0015 REM Initialize freq first! 0016 POKE AUDF,127 0017 REM Start interrupt 0018 Q=USR(SET) 0019 REM Our first beat 0020 FOR D=1 TO 100:NEXT D 0021 REM Play melody 0022 BYTE=95 0023 POKE AUDF,BYTE 0024 C=C+1:IF C>3 THEN C=0 0025 X=X+7:IF X >80 THEN X=X-80 0026 Y=Y+1:IF Y>48 THEN Y=0 0027 COLOR C 0028 PLOT X,Y:DRAWTO 159—X,Y 0029 DRAWTO 159—X,95—Y:DRAWTO X,95-Y 0030 DRAWTO X,Y 0031 READ BYTE 0032 IF BYTE<> —1 THEN 0023 0033 REM Turn of interrupt 0034 Q=USR(CLEAR) 0035 REM Wait for key press 0036 IF PEEK(764)=255 THEN 0036 0037 END 0038 REM Machine language routines 0039 DATA 120,169,35,141,16,2,169,6 0040 DATA 141,17,2,165,16,9,1,133,16 0041 DATA 141,14,210,208,10,120,165 0042 DATA 16,41,254,133,16,141,14 0043 DATA 210,88,104,96,138,72,174 0044 DATA 57,6,189,58,6,141,1,210 0045 DATA 232,138,41,7,141,57,6,104 0046 DATA 170,104,64,16,18,20,24,31 0047 DATA 16,16,16,-1 0046 REM 0049 REM Melody data 0050 DATA 80,127,95,80,120,95 0051 DATA 80,120,95,80,120,90,71,120 0052 DATA 90,71,127,101,71,127,95 0053 DATA 80,127,95,85,143,101,85 0054 DATA 161,127,95,161,127,161 0055 DATA 192,192,192,-1
Rutina En Lenguaje Ensamblador De Sonido Usando Una Interrupción
TITLE 'Interrupt Snd Demo' ;OS equates IRQEN = $D20E ;IRQ enable POKMSK = $10 ;shadow for IRQEN AUDF = $D200 ;freq register AUDC = $D201 ;volume register VTIMR1 = $210 ;timer vector ; ORG $600 ;Set and Clear are to turn ;the sound routine on and off SET SEI LDA #LOW TIMRI ;point to STA VTIMR1 ;sound LDA #HIGH TIMR1 ;routine STA VTIMR1+1 LDA POKMSK ;enable it ORA #1 STA POKMSK STA IRQEN BNE SET2 CLEAR SEI LDA POKMSK ;kill rout AND #$FE STA POKMSK STA IRQEN SET2 CLI PLA ;remove args RTS ;back to Basic ; ;here's the interrupt sound routine TIMRI TXA ;save X PHA LDX WINDX ;get wave X LDA WAVE,X ;get audc value STA AUDC ;& place it INX ;next step TXA ;do wraparound AND #7 STA WINDX PLA ;restore X TAX PLA RTI ; WINDX DS 1 ;wave index ;waveform table WAVE DB $10,$12,$14,$18 DB $1F,$10,$10,$0 END
Leer la siguiente columna que es modulación por ancho de pulso.
Publicado en revista Softline Volumen 2 de Julio y Agosto del 1983, páginas 19 al 20.