Download Emulación del hardware de audio del Commodore Amiga

Document related concepts

Modulación por impulsos codificados wikipedia , lookup

Frecuencia de muestreo wikipedia , lookup

Grabación y reproducción de sonido wikipedia , lookup

Transcript
Emulación del hardware
de audio del
Commodore Amiga.
Digitalizador y reproductor
estéreo de sonido
digitalizado.
Análisis e implementación del
emulador.
Miguel Angel Rodríguez Jódar
Departamento de álgebra, computación, geometría y topología
Facultad de Informática y Estadística
Universidad de Sevilla, 1995
Emulación del hardware
de audio del
Commodore Amiga.
Digitalizador y reproductor
estéreo de sonido
digitalizado.
Análisis e implementación del
emulador.
Miguel Angel Rodríguez Jódar
Director de proyecto: Prof. Gabriel Jiménez Moreno
INDICE GENERAL
1.- Introducción al registro digital.
1.1.- Registro analógico y registro digital. Historia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1
1.2.- Descripción del proceso de digitalización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6
1.2.1.- El proceso de discretización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6
1.2.2.- El proceso de cuantización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.10
1.3.- Tecnología de la digitalización del sonido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.13
1.4.- Manipulación de señales digitalizadas: efectos de sonido . . . . . . . . . . . . . . . . . . . . . . . . . 1.16
1.5.- Compresión del sonido digitalizado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.21
1.6.- Almacenamiento del sonido digitalizado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.23
2.- Introducción al hardware de audio del Commodore Amiga.
2.1.- El circuito integrado 8364 o PAULA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1
2.2.- Descripción del funcionamiento del sistema de audio en el Amiga . . . . . . . . . . . . . . . . . . . 2.3
3.- Introducción al secuenciamiento musical.
3.1.- El secuenciamiento como instrumento de composición musical . . . . . . . . . . . . . . . . . . . . . 3.1
3.2.- El lenguaje de composición musical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3
3.3.- Los secuenciadores en el Amiga. El formato MOD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.7
4.- Estudio de la viabilidad de la emulación en un PC AT 386.
4.1.- El temporizador programable 8254 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1
4.2.- El controlador programable de interrupciones 8259A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4
4.3.- El puerto paralelo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6
4.4.- Ejecución en background. Degradación del rendimiento del sistema . . . . . . . . . . . . . . . . . 4.9
4.5.- Prueba de emulación de un canal digital por el puerto paralelo . . . . . . . . . . . . . . . . . . . . . 4.11
4.6.- Reproducción de varios canales digitales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.14
5.- El modo 32-bit flat pointer en modo real o REALMEM.
5.1.- El modo real y protegido en un i80386 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1
5.2.- El modo REALMEM 32 bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4
5.3.- El gestor de memoria extendida XMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6
6.- Descripción del hardware de audio a implantar en el PC.
6.1.- Esquema funcional y eléctrico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1
6.2.- Programación de la tarjeta de sonido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.14
7.- La rutina de ejecución del intérprete MOD.
7.1.- Descripción del funcionamiento del intérprete MOD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1
7.2.- Listado fuente de la biblioteca de rutinas para cargar y ejecutar MOD’s . . . . . . . . . . . . . . 7.22
A.- Anexos
1.- Bibliografía . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.1
2.- Agradecimientos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A.3
3.- El altavoz interno. Reproducción de música digital usando la modulación PWM . . . . . . . . A.4
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.1
1. INTRODUCCION AL
REGISTRO DIGITAL.
1.1.- Registro analógico y registro digital. Historia.
A principios de siglo con el fonógrafo de Edison se establecieron las bases de lo que debía ser el
registro analógico del sonido. Este consiste a grandes rasgos en convertir las variaciones de presión del
aire producida por los instrumentos musicales, que llamamos sonido, a otro tipo de variaciones
susceptibles de poder ser almacenadas en un medio, y de volver a ser convertidas de nuevo en sonido.
En los primeros tiempos del registro analógico se hacía incidir las variaciones de presión del aire sobre
una membrana adosada a un estilete grabador. Este estilete se movía sobre un cilindro recubierto de cera
o parafina. El cilindro giraba sobre su eje mientras avanzaba lentamente, con lo que el estilete nunca
pasaba dos veces por el mismo sitio en cada vuelta sino que dibujaba una espiral a todo lo largo de la
superficie lateral del cilindro. El sonido al incidir sobre el mecanismo membrana-estilete hacía que
vibrase éste con la misma intensidad y frecuencia que lo hacía el aire de su alrededor, y esa vibración se
reflejaba en la cera formando surcos que dibujaban el aspecto de la onda sonora captada.
Una vez seca la cera, se volvía a pasar el estilete por los surcos de la misma manera y a la misma
velocidad con lo que el estilete se movía siguiendo el dibujo antes creado. El movimiento se amplificaba
mecánicamente mediante una bocina para que fuese audible.
Este mecanismo que en esencia se sigue usando en los giradiscos de los equipos HIFI
usa el método más simple de codificación del sonido, a base de grabar las vibraciones mecánicas que
produce. Realmente no hay una transducción, es decir, una conversión de una variación de energía en una
variación de otro tipo de energía ya que sólo se usa las ondas mecánicas que transmiten las vibraciones
a través de medios elásticos como el aire o el metal del mecanismo del fonógrafo.
Obsérvese que no era posible una posterior manipulación del sonido, salvo modificar la velocidad de
reproducción o reproducir la grabación hacia atrás.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.2
Con el auge de la electricidad surgieron los primeros transductores eléctricos: el micrófono en su
concepción primitiva consistía en dos electrodos separados por una capa de carbón granulado que hacía
variar su resistencia al variar la presión sonora que incidía sobre él. Una corriente continua que atravesase
dicho micrófono experimentaría variaciones de intensidad proporcionales a aquéllas. Dichas variaciones
podían ser amplificadas mediante válvulas electrónicas y dirigidas hacia un altavoz. Este es el transductor
opuesto al micrófono y convierte las variaciones de tensión e intensidad eléctricas en variaciones de la
presión sonora.
La tecnología de los altavoces ha variado poco desde su concepción. Este dispositivo consta de una
bobina eléctrica móvil adjunta a un cono de cartón al que hace vibrar. La bobina se mueve dentro del
campo magnético creado por un imán permanente. La señal amplificada se hace pasar por esta bobina que
crea un campo magnético que repele en mayor o menor medida al campo magnético del imán permanente
moviéndose, junto con la membrana.
La utilización de señales eléctricas para conducir el sonido trajo muchas ventajas en el diseño de
aparatos reproductores de discos que empezaron a formar parte del mobiliario doméstico. A su vez, la
circuitería de estos dispositivos iba complicándose añadiendo mandos de volumen, tono, ecualizadores,
etc...
Paralela a la evolución de la grabación en disco mediante aguja grabadora, surgió y evolucionó la
grabación magnética. En ésta, el sonido una vez convertido a electricidad modula el campo magnético
de una bobina por la que pasa una cinta de plástico recubierta en su superficie de un material con alta
remanencia magnética a una velocidad constante. Las variaciones del flujo magnético magnetizan de
forma variable la sección de cinta magnética situada en el entrehierro de la bobina. En la reproducción
se hace pasar la cinta magnetizada por la bobina. Las variaciones del flujo magnético inducen una
pequeña corriente en la bobina que, una vez amplificada, puede ser escuchada por el altavoz.
En todos los sistemas de grabación de sonido vistos hasta ahora hay algo en común: existe un medio
susceptible de ser impresionado por una energía que varía de la misma forma que lo hace el sonido que
se quiere almacenar. Esta impresión se realiza de manera continua, a lo largo de dicho medio,
almacenando desde sutiles cambios de volumen, hasta sonidos muy altos, existiendo una gama infinita
de volúmenes intermedios, gama limitada sólo, en principio, por las imperfecciones que pueda tener el
medio usado para la grabación y a la precisión de los transductores usados en el proceso. Esta forma de
grabar sonido se denomina registro analógico.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.3
Cuando se ha explicado el proceso de grabación en disco o cinta no se ha tenido en cuenta un factor
importante: el ruido. En efecto, todo proceso que conlleve la utilización de electricidad debe contar con
que los componentes electrónicos generan ruido en mayor o menor medida. Además, la precisión de los
transductores no es ilimitada, por lo que el sonido escuchado no será el mismo en una reproducción que
en la siguiente. De hecho, la interacción transductor-medio degrada este último, de modo que cada vez
el sonido grabado se escucha un poco peor.
Para paliar en alguna medida este efecto se han diseñado algunos sistemas tanto de reducción de ruido
como para evitar producirlo. Entre los primeros se encuentra el sistema Dolby, que en su versión B (la
más extendida en el ámbito doméstico) se usa en la grabación y reproducción de cintas magnéticas. El
problema que intenta paliar este sistema es el llamado ruido de modulación que se produce durante la
grabación de la cinta. Este ruido existe durante todo el pasaje musical aunque normalmente se ve ahogado
por la diferencia de volumen del sonido grabado respecto a él; pero en pasajes musicales más sosegados
sí que se nota como un siseo o ruido blanco. Realmente no es un ruido blanco ya que su espectro de
frecuencias se sitúa en la parte alta del rango auditivo, a partir de los 7 Khz.
La manera en que funciona es la siguiente: se sabe experimentalmente cuál es el nivel sonoro de este
ruido respecto a la señal grabada, y el rango de frecuencias en las que actúa, así que en grabación, se hace
pasar el sonido a grabar por un filtro activo de bajo ruido que sube el nivel sonoro tantos dB como los
que se sabe que posee el ruido de modulación pero sólo para frecuencias por encima de los 7 Khz. La
señal así obtenida se graba en la cinta, junto con el ruido de modulación.
En la reproducción la señal captada por la cabeza lectora lleva tanto la señal sonora como el ruido de
modulación. Esta se hace pasar por otro filtro que actúa de manera contraria al usado en la grabación, esto
es, atenúa en un cierto nivel todas las frecuencias superiores a 7 Khz. Con esta atenuación el ruido de
modulación desaparece y la señal de sonido que antes se grabó con dichas frecuencias amplificadas
recupera su nivel original.
En el terreno de la reproducción de discos el problema al que había que enfrentarse fue la diferencia
de nivel de señal entregada por la aguja del giradiscos es menor cuanto más alta era la frecuencia a
reproducir. Esto es debido a que el vástago porta-aguja es relativamente largo lo que hace que su
frecuencia de resonancia sea menor, y por tanto, presente una inercia mecánica mayor en frecuencias
altas.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.4
La solución adoptada se conoce como norma de ecualización RIAA. El sonido grabado en un disco
tiene atenuadas las bajas frecuencias y realzadas las altas frecuencias de manera que la aguja siempre
ofrece una inercia mecánica constante en todo el espectro de frecuencias audibles. La señal entregada al
amplificador pasa antes por el corrector RIAA que linealiza la señal de audio a la vez que la amplifica
para poder manejarla con el menor ruido posible.
Además del problema del ruido, existe otro muy importante, debido a la mecánica encargada de mover
el medio de almacenamiento ante el transductor. Este movimiento que debería ser constante no lo es por
razones de precisión, y esto origina fluctuaciones en la frecuencia de la señal captada.
A principios de la década de los 80 los laboratorios de Philips crearon el disco compacto (compact
disc o CD). Este medio ofrecía características revolucionarias respecto a sus predecesores, y todo ello
basándose en el registro digital.
Se ha indicado anteriormente que la información guardada mediante el registro analógico podía tomar
cualquier valor entre unos límites, que por la imprecisión de los transductores, dicha información se
recuperaba de forma más o menos ambigua, y que en el proceso de reproducción era degenerativo, o sea,
que en cada reproducción empeoraba la calidad del sonido.
Todo ello es debido a que el registro analógico traduce las variaciones de presión sonora en
variaciones de algún tipo de energía susceptible de ser almacenada, pero no nos ofrece ninguna garantía
de que estas variaciones almacenadas reflejen fielmente el sonido que las causó. Simplemente se limitan
a estar ahí.
En el registro digital se intercala una operación más con la señal antes de ser grabada: la digitalización.
Esta operación, a groso modo, asigna una serie de números a una señal sonora, y son éstos los que se
graban en el medio. Las ventajas de codificar señales mediante números son múltiples: en principio, y
dado que son números, se puede operar con ellos normalmente, y según la operación se modificará de una
forma u otra la señal a la que van asociados. Esto se denomina procesamiento digital.
Además de esto, su grabación es más sencilla y fiable. Ya no hay que tratar con variaciones sutiles de
la información porque un número se puede almacenar en formato binario con lo que sólo necesitamos
discernir entre dos niveles de información, que se pueden escoger de manera que el error producido al
confundir uno con otro sea muy pequeño.
Si a esto añadimos que se pueden aprovechar todos los mecanismos de detección y corrección de
errores, compresión de datos, etc... podemos asegurar que el registro digital es mucho más fiable que el
analógico, aunque no está exento del todo del problema del ruido.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.5
El primer soporte digital fue, como ya se apuntó, el CD. Este emplea para almacenar la información
binaria tiras de agujeros y no-agujeros formando una espiral desde el borde del disco hasta su centro.
Cada pequeño agujero llamado depresión representa un 0, mientras que la no existencia de agujero en una
zona representa un 1.
El CD se lee mediante un rayo láser haciéndolo incidir en dichos agujeros, y reflejándose hacia una
parte u otra según lo haya o no. De esta manera se recuperan los datos numéricos grabados en el disco
y se tratan por el sistema reproductor digital.
Con la llegada de los ordenadores electrónicos, que funcionan bajo el mismo principio de unos y ceros,
el registro digital se ligó de manera permanente a ellos, aprovechándose de su potencia de cálculo. De
esta manera, la información musical no solo se guarda en discos CD sino también en la memoria de un
ordenador, o en un simple fichero en el disco duro. Sólo varía el mecanismo para leer dichos datos
numéricos.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.6
1.2.- Descripción del proceso de digitalización
La digitalización de un sonido es el proceso por el cual se representa una señal sonora mediante una
serie de dígitos que merced a un proceso contrario devuelve la señal original.
Se ha comentado el hecho de que los sistemas de registro analógico tienen una precisión teórica
infinita. Esto es, pueden almacenar cualquier nivel de señal que esté dentro de los límites aceptados por
el sistema de registro. Esto no se cumple en el registro digital, en el cual se graban "instantes" de la señal
sonora. Se demostrará intuitivamente que, para el caso del sonido, estos instantes grabados nos permiten
reconstruir la señal entera sin pérdidas.
Antes de pasar a la sección siguiente, conviene recordar que estamos manejando señales con
frecuencias comprendidas entre 20 y 20.000 Hz que corresponde al rango de percepción del oído humano.
Este tipo de señal, por tener un mínimo y un máximo de frecuencia se denomina señal limitada en
banda. Esta limitación será la que permita al sistema de registro digital poder trabajar perfectamente.
Las etapas de la digitalización del sonido son dos: discretización y cuantización.
1.2.1.- El proceso de discretización.
Se ha introducido la cuestión de que para digitalizar un sonido hay que tomar muestras del
volumen del mismo. Ahora bien, ¿cuántas muestras hay que tomar para poder decir que se ha
guardado toda la información que contiene esa señal?. Para dar respuesta a esta pregunta es
necesario analizar el tipo de información que contiene una señal de audio. [GRE89]
A partir de ahora la consideraremos como una función en el tiempo que toma un valor
determinado de volumen V comprendido ente un máximo y un mínimo, en cada instante de
tiempo t.
Esta función es continua en el tiempo, como lo son prácticamente todas las funciones que
reflejan sucesos de la Naturaleza, y además el estar limitada en banda, el volumen no puede variar
muy rápidamente en un intervalo de tiempo muy pequeño.
Teniendo en cuenta estas premisas vamos a estudiar la señal de audio desde el punto de vista
de la frecuencia.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.7
Sea S(t) definida en [t1,t2] una función que representa a una señal de audio limitada en banda
como ya se ha descrito, en un intervalo de tiempo (Fig. 1.2.1.1). Entonces dicha función se puede
escribir de la forma siguiente:
S(t)=E ancos(nT)+bnsen(nT)
Lo cual nos dice que cualquier señal de audio puede ser generada a partir se señales
sinusoidales de frecuencias 1/T, 1/2T, 1/3T, etc...
Figura 1.2.1.1: Señal analógica de audio.
Estas señales son los armónicos de la señal original. Al estar la señal limitada en banda la
suma de armónicos anterior será finita, siendo el último término de la suma el correspondiente
al armónico de frecuencia igual a la frecuencia máxima que genera la señal que son 20.000 Hz.
Los an y bn son los coeficientes de Fourier de la señal y expresan el volumen que la señal posee
para cada frecuencia en particular.
La idea entonces consiste en averiguar cuánta información hace falta para poder reproducir sin
problemas el armónico de frecuencia más alta. Si nos fijamos en la componente de 20.000 Hz,
vemos que consiste en una señal sinusoidal que parte del cero, alcanza un valor máximo, vuelve
a pasar por cero, alcanza un valor mínimo, y vuelve otra vez a 0.
Por ser una señal sinusoidal sabemos cómo generarla. También sabemos cuál es su frecuencia;
lo único que nos deben dar son los valores máximo y mínimo que toma, lo que nos da:
f(t)=MAXIMO*sen(2*B*20000t) si 0#t<B
f(t)=MINIMO*sen(2*B*20000t) si B#t#2B
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.8
Esto nos dice que bastan dos muestras por período para reconstruir la componente de máxima
frecuencia de la señal de audio. El mismo razonamiento sigue para frecuencias inferiores a ésta,
sólo que la función f(t) resultante tendrá más de dos ramas, pero se reconstruirá con más facilidad
que si fueran sólo dos. Ello nos conduce a la conclusión de que para digitalizar una señal de audio
limitada en banda y con una frecuencia máxima de 20.000 Hz hay que tomar como mínimo,
muestras a una frecuencia de 40.000 Hz.
Esta frecuencia de muestreo mínima, hallada aquí de forma intuitiva, es el resultado de aplicar
el teorema fundamental del muestreo, y la frecuencia obtenida se suele llamar frecuencia de
Nyquist [ANG90]. En la figura 1.2.1.2 se puede observar la toma de muestras a la señal original
en determinados instantes.
Figura 1.2.1.2: Señal de audio discretizada en el tiem po.
Cada instante de sonido muestreado se traducirá en una posición en la memoria de
almacenamiento digital de nuestro sistema de registro digital. Se ve que cuanto más alta es la
frecuencia máxima mayor debe ser la frecuencia de muestreo, y por tanto mayor será el espacio
ocupado por la grabación digital.
En la práctica no se emplea la frecuencia mínima de muestreo de 40.000 Hz para registrar un
sonido, sino que se usan 44.100 Hz. Esto se debe a lo siguiente: [CHR93] [GRE89]
Durante la reproducción del sonido digital se generan tres señales: una es la señal que se está
oyendo en ese momento y tiene una frecuencia fs; las otras dos tiene como frecuencias la suma
y la diferencia de la frecuencia de muestreo fm con la frecuencia de la señal fs. Para la
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.9
reconstrucción de la señal de audio se usa un filtro paso-bajo con una frecuencia de corte de
20.000 Hz, pero este filtro no tiene una pendiente de atenuación infinita, sino que el nivel de señal
que pasa por él desciende a un determinado ritmo. Así, si el filtro es de primer orden atenuará 20
dB/octava y si es de segundo orden, 40 dB/octava. Se pueden construir filtros de mayor orden,
pero resultan más costosos y más sensibles a perturbaciones, autooscilaciones, etc...
Por tanto el filtro que se emplea tiene una determinada pendiente de atenuación para señales
mayores que 20.000 Hz, asegurando una atenuación muy fuerte al llegar a los 40.000 Hz.
Obviamente la componente generada fm+fs no llegará al sistema amplificador, pero la componente
fm-fs puede caer dentro del límite superior de la banda de audio y cruzar sin problemas el filtro
pasa-bajos añadiéndose a la señal de audio y distorsionarla.
Dado que fs como mucho valdrá 20.000 Hz, y queremos que fm-fs sea lo suficientemente alta
para que no cruce el filtro, se sube fm hasta 44.100 Hz, con lo que la primera componente residual
fm-fs valdrá 24.100 Hz, más de 4 Khz respecto a la frecuencia de corte de 20.000 Hz, con lo que
nos aseguramos de que dicha componente será rechazada por el filtro, aunque éste no tenga una
pendiente de atenuación fuerte (Figura 1.2.1.3).
Figura 1.2.1.3: Com portam iento del filtro pasabajos
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.10
1.2.2.- El proceso de cuantización.
Es el proceso en el cual se aproxima el valor real de cada muestra a un valor definido y con
un formato manejable por el ordenador. Al contrario que en la discretización en la que no se
producía ninguna pérdida de información si se trabaja con la frecuencia adecuada, en este caso
se va a producir un error inherente al proceso, que en el caso de una señal de audio puede ser
tolerable con una cierta facilidad. [GRE89]
Gráficamente hablando, se puede ver la cuantización de la siguiente manera: si tenemos la
señal de audio ya muestreada y la representamos en los ejes de tiempo y volumen como se hizo
con la señal original, la gráfica resultante será un conjunto de puntos con una distancia horizontal
entre cada uno de ellos igual al período de muestreo (el inverso de la frecuencia de muestreo).
Cada punto corresponde a un valor en el eje de los tiempos correspondiente al instante en que se
tomó esa muestra, y otro valor en el eje de volúmenes que corresponde al volumen de la señal en
ese instante.
Si ahora trazamos líneas horizontales paralelas al eje de tiempos y asignamos un número a
cada una de ellas, se observará que los puntos que componen nuestra gráfica caen en la gran
mayoría entre dos de estas líneas (que llamaremos niveles de cuantización o niveles de
decisión). La cuantización consistirá entonces en sustituir el valor real de volumen de cada
muestra por el número correspondiente a la línea horizontal que tengan más cerca. Ese número
ahora tendrá un valor definido y dentro de un rango conocido, por lo cual se puede almacenar de
manera convencional en la memoria (figura 1.2.2.1).
Figura 1.2.2.1: Señal de audio discretizada y cuantizada.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.11
El error cometido en el proceso de cuantización de cada muestra será igual (de forma gráfica)
a la distancia entre el punto que representa a la muestra y la línea que se ha elegido como
aproximación. Se intuye que cuantas más líneas se utilicen, menor será el error cometido y por
tanto mayor será la calidad del sonido digitalizado; pero esto tiene un inconveniente y es la
cantidad de memoria que se necesita para almacenar el valor de cada muestra. Si usamos 16
niveles de cuantización podemos almacenar dos muestras por byte, con una calidad de sonido
bastante regular a no ser que se trate de señales simples o voz humana. Si se usan 256 niveles,
tendremos una muestra por byte con una calidad de sonido muy buena para propósitos generales,
y si se usan 65536 niveles de cuantización el sonido resultante no podrá distinguirse del original
pero cada muestra ocupará dos bytes.
Una medida de la calidad del sonido en un sistema de audio es la relación señal/ruido (SNR)
que se define como:
Entonces se demuestra que una señal digitalizada con n bits (lo que significa 2n niveles de
cuantización) tiene una SNR igual a:
SNR=4,6+6n
Para fijar ideas, tener en cuenta que la SNR que da un plato giradiscos es mayor de 40 dB, y
que un lector de CD puede alcanzar sin problemas los 90 dB.
Pero el problema fundamental con que se tiene que enfrentar los sistemas de audio digitales
consiste en un tipo de distorsión que se deriva del proceso de cuantización y que se denomina en
algunos textos como distorsión de cruce cero.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.12
Cuando se escucha en un sistema de audio convencional una pieza musical que contiene
pasajes a bajo volumen, nuestro oído capta los sutiles matices de volumen que se producen
durante éste. Estos cambios tenues de volumen se producen a nivel eléctrico muy cercanos al
punto de 0 voltios que corresponde al punto estático de trabajo del circuito amplificador del
sistema. Al variar muy poco el punto de trabajo dinámico del punto estático la fidelidad con la
que se reproducen esos sonidos es mayor que si el volumen fuera mayor. En este último caso el
punto de trabajo dinámico se aleja del punto estático y se corre el peligro de saturar la etapa de
amplificación dando lugar a lo que se conoce como distorsión de corte.
En cambio, si se escucha el mismo pasaje en un sistema digital ocurre lo contrario. En este
caso, al digitalizar la parte a bajo volumen, las muestras quedan casi todas contenidas entre dos
únicos niveles de cuantización perdiendo todos los pequeños cambios de volumen por no haber
niveles intermedios. Un fenómeno acusado de este tipo causa un ruido como un crujido
acompañando al pasaje de bajo volumen. Este crujido es causado por las transiciones bruscas de
un nivel de cuantización al inmediato superior o inferior en lugar de hacer una transición suave
como estaba previsto en la señal original.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.13
1.3.- Tecnología de la digitalización del sonido.
En el tratamiento digital del sonido existen dos dispositivos fundamentales: el ADC o conversor
analógico-digital, y el DAC o conversor digital-analógico.
Alrededor de estos dos dispositivos existen otros auxiliares que potencian y ayudan en el diseño de
un sistema digital. Como ejemplo se pueden citar los circuitos de muestreo y retención, los circuitos de
retardo analógico, los filtros digitales, los circuitos de compresión ADPCM y los DSP (procesadores
digitales de señal) que combinan muchos de éstos últimos. [TRA87]
El conversor analógico-digital.
Muestrea la señal de audio existente en su entrada y la codifica entregando su valor binario en un bus
de salida. La señal entra a un circuito de muestreo y retención que funciona como una memoria analógica
reteniendo el valor de tensión que aparece en la entrada cuando el circuito recibe un pulso activo. Este
pulso se repite con una cadencia igual a la frecuencia de muestreo que se aplica a la señal.
La tensión almacenada sirve de entrada al conversor propiamente dicho. Este necesita una tensión
constante en su entrada para poder cuantizarla sin errores, y por eso se hace pasar antes por el circuito de
muestreo y retención.
Hay varias técnicas para realizar la cuantización. La más sencilla y a la vez la más rápida, pero
también la más cara es la usada por los llamados ADC flash-converter. Estos disponen de una batería de
2n comparadores analógicos dónde n es el número de bits de resolución del conversor. Cada comparador
compara la señal de entrada con una fracción de la señal máxima que soporta el ADC y entrega un valor
binario como resultado. Los 2n resultados se aplican a un codificador que proporciona la salida en
notación binaria convencional, o en complemento a 2.
Este tipo de ADC no precisa de una señal de reloj para su funcionamiento ya que todos los elementos que
intervienen son combinacionales. Con frecuencia ni siquiera necesitan de un circuito S&H (muestreo y
retención) ya que son muy rápidos. El coste de este tipo de ADC viene dado por la necesidad de integrar
en el CI los 2n comparadores. Para una resolución de 8 bits se necesitan 256 comparadores, y para 16 bits
se necesitarían 65.536.
Otro tipo de ADC es el de cuenta y comparación o ADC rampa (Figura 1.3.1). Es de un diseño muy
sencillo pero resulta demasiado lento para algunas aplicaciones. La señal de audio muestreada por el S&H
es enviada a un comparador analógico. La otra entrada del comparador viene de la salida de un DAC que
controla un contador. Inicialmente este contador está a 0, y cuando se inicia la conversión, el
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.14
contador empieza a incrementar su cuenta, con lo que la tensión aplicada al comparador empieza a
acercarse a la de la señal. En el momento en que la rebasa, el comparador conmuta su salida lo que hace
parar al contador. El valor presente en ese momento en el contador es el valor binario de la señal que
queremos digitalizar.
De concepción parecida al anterior pero más rápido es el ADC de aproximaciones sucesivas. En éste
se cambia el contador por un SAR (registro de aproximaciones sucesivas). Con este método se emplean
n ciclos de reloj para realizar la conversión. El SAR se carga inicialmente con el valor 1000.....0 y se
realiza la primera comparación. Si la señal de entrada es mayor que la del SAR se deja el bit más
significativo como está; si no, se pone a 0. En el siguiente ciclo de reloj se repite el proceso para el bit
n-1 poniéndose en principio a 1 y conmutando a 0 según la comparación. Al cabo de los n ciclos el valor
contenido en el SAR es el valor digital que más se aproxima a la señal de entrada (Figura 1.3.1).
Figura 1.3.1: Cronogram a de una conversión con un ADC ram pa.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.15
Figura 1.3.2: Cronogram a de una conversión con un ADC de aproxim aciones sucesivas.
El conversor digital-analógico.
Toma en su bus de entrada los datos digitales más una señal de validación, si fuera necesaria, y genera
una tensión analógica proporcional a dicho dato. Son dispositivos más sencillos en cuanto a su
concepción, pero deben ser muy precisos.
En su concepción más simple se compone de una red de resistencias más unos interruptores analógicos
controlados por cada uno de los bits del dato a convertir. Cuando un bit está a 1 cierra un interruptor y
deja pasar una cierta cantidad de intensidad a través de la red. Las diferentes combinaciones de 1's y 0's
hacen variar la intensidad total en la red, y gracias al diseño de ésta, se produce en al salida del conversor
una intensidad o una tensión proporcional al valor binario del dato de entrada.
La señal que proporcionan a la salida debe ser filtrada para linealizar la señal de salida. Si no se filtra,
ésta aparece en el osciloscopio como una señal analógica discontinua, tal y como la entrega el S&H.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.16
1.4.- Manipulación de señales digitalizadas: efectos de sonido.
Con la posibilidad de poder convertir señales de audio a números se ampliaron las posibilidades de
post-producción del sonido. Esto es, alterarlo una vez grabado.
Con el registro analógico convencional, a pesar de sus limitaciones, se habían diseñado algunos
efectos: se podía cambiar la velocidad y el sentido de la reproducción, se podía distorsionar el sonido,
modularlo en frecuencia y/o amplitud para conseguir efectos de vibrato y trémolo, e incluso se habían
diseñado generadores de eco analógicos, que usaban un muelle fijado por uno de sus extremos a un
altavoz, y por otro a un micrófono. El sonido emitido por el altavoz hacía vibrar el muelle provocando
un sin fin de rebotes en el mismo, que eran captados por el micrófono y vueltos a amplificar.
Todo esto hizo posible la aparición de la llamada música concreta en Francia, precursora de la actual
música electrónica. En aquella el sonido era sometido a estos efectos, haciendo montajes sobre cinta con
las nuevas grabaciones alteradas.
El registro digital no sólo permite la realización de todos estos efectos, sino que además permite otros
no posibles con el registro analógico, y además sin coste alguno de dispositivos, ya que todos los efectos
se pueden realizar mediante cálculos matemáticos con los datos digitales dentro de la memoria de un
ordenador. Existen, no obstante, circuitos que proporcionan de manera directa y en tiempo real estos
cálculos de efectos sonoros: son los DSP o procesadores digitales de señal.
A continuación se escribirán algunos de estos efectos y su forma de calcularlo. [BIN88]
Distorsión: consiste en multiplicar cada dato digital por una constante positiva lo suficientemente grande
para que alguno de los resultados excedan del rango de los datos digitales. Esto es, supongamos que
trabajamos con 8 bits, y nuestro rango va desde el -128 hasta el 127, entonces, al multiplicar la secuencia
-100, -45, -18, 0, 26, 50, 80, 125 por 3 nos da la siguiente: -128, -128, -54, 0, 78, 127, 127, 127. Los
valores que al ser multiplicados exceden del rango son truncados al valor máximo dentro del rango. Esto
se traduce gráficamente en que la señal sufre un corte tanto en el lado positivo como en el negativo. La
distorsión producida se llama distorsión de corte.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.17
Procedimiento Distorsion (A[1..n], factor)
para i:=1 hasta n hacer
temp:=A[i]*factor
si temp>MAXIMO
temp:=MAXIMO
sino
si temp<MINIMO
temp:=MINIMO
finsi
finsi
A[i]:=temp
finpara
Fin
Eco y reverberación: el eco consiste en una repetición del la señal a causa de una reflexión de la onda
en una pared, con una cierta pérdida de potencia.
Para que se pueda hablar de eco, la distancia entre el foco emisor de sonido y la pared debe ser mayor que
17 metros. Estos porque para que el oído humano perciba dos sonidos como sonidos diferentes deben
estar distanciados 0.1 segundos uno respecto al otro como mínimo.
Si no se cumple este requisito, el efecto se denomina reverberación.
El efecto se puede crear mezclando la señal de audio consigo misma, retrasada en el tiempo. Para
retrasarla se puede emplear una memoria gestionada como una cola FIFO, de cuya longitud dependerá
el retraso obtenido (Figura 1.4.1).
Procedimiento Eco (A[1..n], retardo, atenuacion)
para i:=1 hasta n-retardo hacer
A[i+retardo]:=(A[i+retardo]+A[i]*atenuacion)/2
finpara
Fin
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.18
Figura 1.4.1: Diagram a de bloques de una unidad de ECO digital.
Phasing: es un tipo de reverberación en el que la señal sólo es retrasada unas cuantas muestras. En este
caso se percibe un sólo sonido, al estar mezclado dicho sonido con otro casi igual que él, se producen
múltiples reforzamientos y cancelaciones de fase que originan una falsa sensación de variación del "pitch"
o afinación de dicho sonido.
Sliding: efecto parecido al que hacen los guitarristas al deslizar los dedos por una de las cuerdas para
alterar suavemente su tono. Se crea variando la frecuencia de muestreo en reproducción suavemente.
Filtraje digital: consiste en someter los datos digitales a una transformada de Fourier, para después
eliminar sencillamente las componentes de frecuencia no deseadas. Al resultado se le aplica una
transformada inversa. La señal de salida es la versión filtrada de la entrada. Una versión de este
procedimiento aplicable en tiempo real usa la transformada inversa de Euler.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.19
Procedimiento Filtrar_Bajos (A[1..n], frecuencia)
B[1..n]=(0,0,0,......,0)
Transformada_Fourier (A[1..n],B[1..n])
para i:=frecuencia hasta n hacer
A[i]:=0
B[i]:=0
finpara
Transformada_inversa (A[1..n],B[1..n])
Fin
Otra implementación de este efecto se consigue usando la transformada Z de la señal de entrada y la del
filtro a construir. Esta opción resulta en un algoritmo al que se le dan los valores de entrada de la señal
y va produciendo los valores de salida ya filtrados. La sencillez del método posibilita su uso en tiempo
real.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.20
Donde w es la frecuencia de corte del filtro, y T es el período de muestreo de la señal a filtrar.
Falso estéreo: usa la sensación de profundidad que crea el efecto reverberación, pero esta vez no mezcla
las dos señales sino que envía cada una a un altavoz distinto.
Procedimiento Estereo (A[1..n], profundidad)
para i:=1 hasta n-profundidad hacer
DAC_Izquierdo (A[i])
DAC_Derecho (A[i+profundidad])
finpara
Fin
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.21
1.5.- Compresión del sonido digitalizado.
La digitalización de un sonido supone una lista bastante extensa de números que deben almacenarse
en la memoria de un ordenador o el dispositivo de almacenamiento que precise (CD, cinta digital, etc...).
Cada uno de estos dígitos ocupa un espacio físico en dicho medio, por lo que cuanto más largo sea el
sonido a digitalizar más ocupará en memoria.
Sin embargo, la lista de dígitos resultante del proceso de digitalización tiene una característica que
permite "adivinar" hasta cierto punto cuál es el siguiente dato de la lista: al ser dicha sucesión las
imágenes de una función continua cuyos puntos están muy próximos unos de otros y a una distancia
constante, las imágenes también estarán muy cerca. Por otra parte almacenar cada punto de la imagen
cuesta un número determinado de bits, dependiendo de la resolución del muestreo. Ahora bien, al ser los
elementos de esta sucesión muy próximos en valor unos de otros, podemos almacenar la diferencia de
valor que hay de un elemento al siguiente. Esta diferencia será un número muy sencillo que puede ser
almacenado con menos bits que el elemento original.
Ejemplo: sea la sucesión 0,2,2,4,5,7,10,9,8,8. Si la resolución a la que fueron tomadas estas muestras
fue de 16 bits, la sucesión completa ocupará 20 bytes (160 bits). Si en lugar de eso almacenamos sus
diferencias obtenemos la sucesión:
0,2,0,2,1,2,3,-1,-1,0. El primer valor no es una diferencia, sino el primer elemento de la sucesión de
partida; se puede reconstruir la sucesión original a partir de esta sumando todos los elementos desde el
primero hasta aquél cuya posición es la del elemento que queremos hallar.
Ahora cada elemento puede guardarse en complemento a 2 en un espacio de 3 bits, lo que da para este
ejemplo una ocupación total de 30 bits. 5 veces menos que la sucesión original.
Al formato usado en la sucesión de partida, en dónde los datos están sin comprimir se le llama PCM
(Pulse Code Modulation) o modulación por pulsos codificados. La sucesión con los elementos
comprimidos está en formato DPCM (Delta PCM).
El inconveniente de este sistema de compresión aparece cuando la diferencia entre un elemento y el
siguiente es tan alta que sobrepasa la capacidad del formato de bits elegido para los elementos
comprimidos. En ese caso se almacena la máxima diferencia admisible por el formato y se continúan los
cálculos con el valor modificado.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.22
Ejemplo: si en la sucesión anterior, con el formato comprimido de 3 bits continúa de esta forma.
..,9,8,8,2,0,3,... la versión comprimida sería ..,-1,-1,0,-4 (porque -6 no cabe en 3 bits), -4 (en lugar de -2,
ya que ahora la sucesión ha cambiado a 9,8,8,4,0,3), 3,...
Con la aparición del mini-disc de Sony con un menor tamaño y con la capacidad de poder ser grabado
por el usuario, se hizo necesaria la introducción de nuevas tecnologías de compresión del sonido. La
usada por Sony se aprovecha de las "deficiencias del oído humano que es incapaz de percibir
determinados matices de la música que aunque se registran en el CD normal, no son percibidos por el
oyente.
El sistema mini-disc emplea una doble técnica de compresión durante la grabación: una vez
digitalizada la señal ésta es enviada en grupos de 1 Mbit hacia una memoria intermedia que sirve a la
unidad de control para la calibración de la velocidad de giro del disco. Cada grupo de señal se hace pasar
por un DSP que realiza una transformada de Fourier de los datos, y a partir de aquí empieza la
compresión.
No todos los datos resultantes de la transformación se graban: siguiendo la curva de respuesta en
frecuencia del oído humano se descartan aquellas frecuencias cuya potencia no alcanza el umbral mínimo
para ser percibidas, por otra parte todas aquellas componentes en frecuencia cuya potencia sea muy
pequeña en comparación con las componentes inmediatas en valor también son descartadas ya que la
componente de mayor potencia "ahoga" a la de menor potencia con lo que tampoco es percibida por el
oído.
Las componentes de frecuencia que han pasado esta doble selección son las que se realmente se
graban, en formato de 16 bits junto con las marcas de inicio y fin de bloque, y las señales que indican que
falta una determinada componente frecuencial. En la reproducción se van leyendo bloques de señal a una
gran velocidad y son transformadas de nuevo a sucesiones de datos temporales que pasan por un
conversor D/A de 16 bits para ser escuchadas.
Gracias a esta técnica de compresión se pueden grabar hasta 70 minutos en un disco de 3,5 pulgadas.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.23
1.6.- Almacenamiento del sonido digitalizado.
A continuación, y como ejemplo de las técnicas discutidas anteriormente, describiremos la tecnología
de codificación del sonido en un Compact Disc [RIF91]
El sistema de almacenamiento y reproducción del CD fue diseñado, conjuntamente por Philips y Sony
en junio de 1980.
La señal analógica que transmite el sonido es muestreada 44.100 veces por segundo y, a cada muestra,
se le asigna un valor numérico (amplitud de la señal) ente 0 y 216-1. Este valor da un vector binario de
16 componentes, que escribiremos como dos elementos de GF(28). Teniendo en cuenta que
transmitiremos señal estéreo, cada muestra estará formada por cuatro elementos de GF(28), dos para el
canal derecho y dos para el canal izquierdo.
La información es grabada después de haberla codificado concatenando dos códigos RS sobre GF(28),
con interleaving. La longitud de estos códigos es n=28-1=255, su dimensión es k=n-d+1=251 y su
distancia mínima es d=5.
En el canal interno de la concatenación no se usa el código RS(255,d=5), sino el código recortado
hasta una longitud de n=28. Por abuso de lenguaje diremos que utilizamos un código RS(28,d=5), sobre
GF(28). En el canal externo de la concatenación se usa el mismo código RS, recortado hasta longitud
n=32; hablaremos del código RS(32,d=5).
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.24
En el esquema siguiente se recogen los rasgos más característicos del proceso de concatenación.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.25
La grabación en disco se hace en una pista espiral marcando, físicamente, áreas planas y hundidas.
Cada vez que ocurre una transición de un área plana a una área hundida, o viceversa, se lee un 1 y en caso
contrario se lee un 0, según la longitud de la zona recorrida sin cambiar de área. Por ejemplo, en la figura
1.6.1 observamos la secuencia 00 1 000 1 000000 1 00 1 0000 1 000, grabada en el disco.
La transición entre áreas viene dada por los cambios de intensidad de la luz reflejada por el disco,
proveniente de una fuente láser.
Por razones técnicas, en cada área debe haber un mínimo de dos ceros y un máximo de diez. En
principio, los bits que salen de la última matriz de interleaving no cumplen la propiedad anterior y, por
tanto, antes de proceder a la grabación definitiva hay que arreglar la situación. Esto se consigue con la
técnica EFM, que transforma cada símbolo de GF(28) en una secuencia de 17 bits con las propiedades
requeridas. Además, a cada trama de 544 bits se le añaden 27 bits de sincronización y de
direccionamiento, que permitirán la búsqueda rápida de la información.
En total, cada 6 muestras iniciales (24 elementos de GF(28) = 192 bits) se transforman en 571 bits
grabados en el CD. La tasa de transmisión de la información es de 192/571 • 1/3. La tasa de transmisión de
la información, considerando únicamente los códigos, vendría dada por k = (28/32) (24/28) = 24/32 = 3/4.
Cada segundo de música necesita 44.100 muestras, y cada una 571/6 bits. En definitiva, 4,2
Mb/segundo. Cada disco tiene una capacidad de unos 20.000 Mb que, traducido a tiempo, representa unos
80 minutos de audición.
MULTIMDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 1.26
Funcionamiento de los dos códigos concatenados. Proceso CIRC (Cross Interleaved Reed-Solomon
Code). El código RS(32,28) tiene una distancia mínima d=5, puede corregir 2 errores o bien se puede
utilizar para corregir un error y detectar 3. En nuestro caso lo utilizaremos para corregir un único error.
Si en el decodificador encontramos un error lo corregimos. En caso contrario, daremos como borrones
los 28 símbolos que salen del decodificador y entran en el canal externo.
El decodificador externo RS(28,24) tiene distancia mínima d=5 y lo utilizaremos para corregir 4
borrones. Tal como está montada la matriz de interleaving, es posible que este código corrija hasta un
máximo de 112x4=448 borrones de GF(28), es decir 3584 bits de datos, que quedan en 3072 bits de
información real, equivalentes a unos 3 mm en una pista del CD.
Además, en el caso de que un vector a decodificar en el código externo tenga más borrones que los
que se pueden corregir, se daría como nulo y, en su lugar, se haría la interpolación de las palabras anterior
y posterior.
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 2.1
2. INTRODUCCION AL HARDWARE DE
AUDIO DEL COMMODORE AMIGA.
2.1.- El circuito integrado 8364 o PAULA.
Paula es uno de los circuitos de propósito específico diseñados exclusivamente para el
Commodore Amiga. Las tareas de Paula conciernen principalmente en el área de E/S, esto es, el sistema
de disquetes, el puerto serie, el sonido y la lectura de datos analógicos desde el joystick. Además Paula
se encarga de todo el control de las interrupciones del sistema. Todas las interrupciones que ocurren en
el Amiga pasan a través de este integrado. A partir de las 14 posibles fuentes de interrupciones Paula crea
las señales de interrupción para el 68000. Las interrupciones en los niveles 1-6 se generan por las líneas
IPL del 68000. Paula ofrece al programador la posibilidad de permitir o prohibir cada una de las 14
fuentes de interrupciones. [CHR93]
Las transferencias de datos desde disco y la generación de sonido se realizan usando DMA. A
causa de que el controlador general de DMA del Amiga, Agnus, no sabe cuándo está disponible el
próximo dato para la transferencia DMA, Paula tiene una línea de petición de DMA, DMAL.
A continuación se describen las funciones de cada pin.
Bus de datos: D0-D15
Conectado al bus de datos del sistema.
Bus de direcciones de registro: RGA 1-8
Conectado al bus de direcciones. Direcciona los registros internos del chip.
Señales de reloj CCK, CCQ, y pin de réset RES
Petición de DMA: DMAL
Por esta línea, Paula indica al controlador DMA que se necesita una transferencia DMA..
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 2.2
Salidas de audio: AUDL y AUDR
Las salidas AUDL y AUDR (audio izquierdo y audio derecho) son salidas analógicas en dónde Paula
sitúa las señales de audio generadas. AUDL lleva los canales 0 y 3, y AUDR los canales 1 y 2.
Las líneas del interfaz serie: TXD y RXD.
Las entradas analógicas POT0X, POT0Y, POT1X, POT1Y.
Las líneas de manejo del disco: DKRD, DRWD, DKWE.
Las líneas de interrupción: INT2, INT3, INT 6 y IPL0, IPL1 e IPL2.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 2.3
2.2.- Descripción del funcionamiento del sistema de audio en el
Amiga
Centrándonos en el tema de la generación de sonido, PAULA está dotada de 4 generadores de
sonido digital que no son más que 4 conversores D/A que muestrean datos desde la memoria a través de
otros tantos contadores de DMA. Los canales 0 y 3 se mezclan analógicamente y salen por el canal
izquierdo; los canales 1 y 2 lo hacen por la salida derecha.
Cada canal de audio tiene su propio canal de DMA. Dado que la lógica de DMA en el Amiga
opera con palabras de 16 bits se combinan dos muestras en una sola palabra, por esta razón, se necesita
un número par de muestras por cada canal. El byte más significativo se envía siempre antes que el byte
menos significativo.
El conversor D/A requiere que las muestras se almacenen como números de 8 bits en
complemento a 2. A continuación se ofrece un ejemplo de cómo se almacenan dichas muestras. En éste
y en los demás ejemplos de programación del 8364 se asumirá que estamos en el entorno hardware y
software de un Amiga 500.
Start:
dc.b 0, 49, 90, 117, 127, 117, 90, 49, 0, -49, -90, -117, -128, -117, -90, -49
End:
Ahora se debe seleccionar uno de los 4 canales sobre el cual se ejecutará la muestra. El canal de
DMA correspondiente se debe inicializar. Para inicializar los parámetros usaremos 5 registros por cada
canal. Los dos primeros forma un par de registros de direcciones: son AUDxLCH y AUDxLCL, o juntos,
AUDxLC dónde x es el número de canal de DMA correspondiente.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Registro
Nombre
$0A0
AUD0LCH
$0A2
AUD0LCL
$0B0
AUD1LCH
$0B2
AUD1LCL
$0C0
AUD2LCH
$0C2
AUD2LCL
$0D0
AUD3LCH
$0D2
AUD3LCL
Función
Pag. 2.4
Contenido
Puntero a los datos de audio
para el canal 0
Bits 16-20
Puntero a los datos de audio
para el canal 1
Bits 16-20
Puntero a los datos de audio
para el canal 2
Bits 16-20
Puntero a los datos de audio
para el canal 3
Bits 16-20
Bits 0-15
Bits 0-15
Bits 0-15
Bits 0-15
Para la inicialización de estos punteros podemos usar (en el Amiga) la instrucción MOVE.L del
68000:
LEA $DFF000,A5
MOVE.L #Start,AUD0LCH(A5))
; Colocar dirección base de los registros del Amiga.
; Inicializar AUD0LC al principio de la tabla de muestras.
De manera análoga se debe indicar la longitud de la muestra (en palabras de 16 bits) en el registro
AUDxLEN apropiado.
Reg.
Nombre
Función
$0A4
AUD0LEN
Longitud de la muestra en palabras para el canal 0
$0B4
AUD1LEN
Longitud de la muestra en palabras para el canal 1
$0C4
AUD2LEN
Longitud de la muestra en palabras para el canal 2
$0D4
AUD3LEN
Longitud de la muestra en palabras para el canal 3
Para inicializar el valor de la longitud se usará la siguiente instrucción MOVE.W:
MOVE.W
#(End-Start)/2,
AUD0LEN (A5)
Nótese que hemos usado el valor de las etiquetas Start y End definidas en el trozo de código que
corresponde a la tabla de muestras para el canal 0. La diferencia de End-Start es la longitud en bytes de
la muestra. Como necesitamos un valor en palabras, dividimos el resultado entre 2.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 2.5
Ahora programaremos al 8364 para que "toque" la muestra a un determinado volúmen. El valor
del volúmen será un número entre 0 y 64, dónde 64 representa un nivel de 0 dB, 1 corresponde a un nivel
de -36.1 dB y 0 corresponde a un nivel de -4 dB. De esta manera el valor de la muestra queda
multiplicado por la fracción VOLUMEN/64.
Realmente, en el 8364 (a diferencia de lo que después veremos en el PC) cada muestra NO se
multiplica por la fracción anterior de manera digital, ya que esto haría que, a volúmenes bajos, la calidad
de la muestra empeoraría, como se explicó en el apartado sobre los problemas de la cuantización.
Lo que se hace con el valor del volúmen es dar como entrada la parte menos significativa (bits
0-5) a un conversor D/A de 6 bits cuyo valor analógico de salida es el valor Vref de referencia para el
conversor D/A principal de cada canal. El bit 6, que sólo será 1 cuando el valor del volúmen sea 64
servirá de señal de control a un multiplexor analógico situado antes de la entrada Vref del conversor D/A
de sonido. Si el bit 6 vale 0, el multiplexor conectará Vref a la salida del conversor D/A de volúmen. Si
es 1, Vref se conectará directamente a la tensión Vref del conversor D/A de volumen.
A continuación se muestra la tabla dónde se recogen los nombres y direcciones de los registros
de volumen de cada canal:
Registro
Nombre
Función
$0A8
AUD0VOL
Volumen del canal 0
$0B8
AUD1VOL
Volumen del canal 1
$0C8
AUD2VOL
Volumen del canal 2
$0D8
AUD3VOL
Volumen del canal 3
Para inicializar el volúmen usaremos una instrucción MOVE.W análoga a la anterior:
MOVE.W #40, AUD0VOL (A5)
; Canal 0 a volúmen máximo.
El último parámetro que debemos programar en el 8364 es la frecuencia de muestreo.. Este valor
no podemos programarlo directamente en herzios; en lugar de eso, debemos programar al controlador de
DMA que es quien va a hacer el muesteo sobre la memoria, con el número de ciclos de bus que ocurrirán
entre cada salida de dos muestras. Un ciclo de bus tarda 279.365 ns en el Amiga.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 2.6
Para calcular el número de ciclos de bus a partir de la frecuencia de muesteo se usará la siguiente
fórmula:
El valor asignado al ciclo de bus puede estar teóricamente entre 0 y 65535. Sin embargo el rango
real tiene un límite superior. Como se puede observar (figura 2.2.1) cada canal de audio tiene asignada
una ranura de DMA en cada barrido horizontal de video. Esto significa que se pueden leer dos muestras
en cada retrazo horizontal. Esto hace que el valor mínimo posible para AUDxPER sea 124. La frecuencia
de muestreo máxima es por tanto de 28867 Hz. Si se usa un valor menor que éste, el controlador de DMA
no tendrá tiempo de leer las siguientes muestras, y por tanto, las dos que se leyeron por última vez y que
están en el 8364 se volverán a volcar sobre los conversores D/A..
Registro
Nombre
Función
$0A6
AUD0PER
Ciclos de bus para el canal 0
$0B6
AUD1PER
Ciclos de bus para el canal 1
$0C6
AUD2PER
Ciclos de bus para el canal 2
$0D6
AUD3PER
Ciclos de bus para el canal 3
Para asignar a un canal la frecuencia de muestreo podemos hacer:
MOVE.W #508, AUD0PER (A5)
; Asigna frecuencia de muestreo de 7040 Hz.
Una vez que se ha inicializado un canal debemos activar al controlador de DMA para que empieze
el muestreo. Esto ya no depende del 8364 sino que corre a cargo del circuito controlador del DMA. En
el caso del Amiga se activa con:
MOVE.W #$8201, DMACON (A5)
; Pone a 1 AUD0EN y DMAEN
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 2.7
A partir de ahora el DMA realiza el muestreo de los datos en memoria de la manera en que lo
hemos programado. Una vez que ha terminado de leer todas las muestras pulsa una línea de interrupción
que comunica al 68000 este hecho, y vuelve a empezar desde el principio de la muestra.
El 8364 dispone también de otras características que señalaremos sólo de manera indicativa, dado
que no van a formar parte de la simulación. Ente ellas está la posibilidad de usar las muestras de un canal
para modular en frecuencia y/o en amplitud a otro canal.
De esta manera se pueden sintetizar efectos de vibrato y trémolo con un instrumento sin la necesidad de
remuestrear el instrumento.
Como antes se indicó, la frecuencia de muestreo está limitada a unos 28 kHz a causa de la
asignación de tiempos por el controlador de DMA. Si se supera esta frecuencia no se leen nuevas
muestras de memoria sino que se envían al DAC las dos últimas muestras guardadas dentro de los
registros del 8364. Este puede aún enviar las dos muestras al límite de la frecuencia de muestreo que
admite el 8364, que es de unos 3,5 Mhz (corresponde a un valor de 1 en AUDxPER). Si hacemos que una
de las muestras sea 128 y la otra -127, el 8364 generará una señal cuadrada de 1,7 Mhz. Esta señal no
pasará el filtro paso baja instalado en el Amiga, pero existen tomas exteriores en el puerto serie
conectadas directamente a los pines AUDR y AUDL del 8364. Dado que la señal generada de esta manera
se puede modular en amplitud y/o frecuencia es posible teóricamente hacer funcionar a Paula como un
módem o un modulador de audio.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.1
3. INTRODUCCION AL
SECUENCIAMIENTO MUSICAL.
3.1. El secuenciamiento como instrumento de composición
musical.
El secuenciamiento consiste en la transcripción de un pasaje musical en una secuencia de
símbolos que representan las evoluciones (cambios de tonalidad y volúmen) de los distintos instrumentos
a través del tiempo. Al sistema que interpreta dichos símbolos y reproduce el pasaje musical se le
denomina secuenciador.
Esta transcripción, proceso mucho más antiguo que el tratamiento electrónico del sonido, hizo
posible el transmitir pasajes musicales a través del tiempo sin deterioro de su contenido.
El secuenciamiento es, en sí mismo, una forma de digitalizar la música ya que se basa en la
discretización y la cuantización. En la discretización se divide el tiempo en partes iguales asignando
determinadas propiedades a cada parte. Dichas propiedades determinan el ritmo de la composición. La
cuantización en este contexto consiste en identificar cada una de las notas de la composición y asignar
a cada una una altura tonal (frecuencia).
Pero a diferencia de la digitalización estándar que define una sucesión numérica en el tiempo a
muy alta resolución, el secuenciamiento define las características de la composición a intervalos de
tiempo mucho más amplios., lo que significa una mayor libertad en la ejecución. De aquí que el lenguaje
musical definido por el secuenciamiento sea ambiguo, y cada ejecución no tiene por qué ser igual a la
anterior; algo que no ocurre en la reproducción de música digitalizada.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.2
A través del tiempo este lenguaje musical se ha ido enriqueciendo con nuevos símbolos que
completan, matizan o añaden significado a cada instante de tiempo dentro de la melodía. Esto ha definido
un lenguaje de composición e interpretación musical apto para la interpretación de música por parte de
un músico humano, pero no por parte de un secuenciador electrónico.
A partir de este lenguaje, que se definirá en los párrafos siguientes, se han definido otros que son
una simplificación del primero: unos para interpretar determinados tipos de música, o para tocar
determinados instrumentos, y otros aptos para su interpretación a salvo de ambigüedades, por parte de
un ordenador.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.3
3.2. El lenguaje de composición musical. La partitura.
Es un lenguaje simbólico, independiente del idioma del compositor, que permite representar la
evolución tonal de uno o más instrumentos a través del tiempo.
Su representación escrita es el pentagrama. El conjunto de pentagramas que representa a la
totalidad de la melodía se le denomina partitura.
Figura 3.2.1: Escala m usical en el pentagram a.
Un pentagrama se representa con cinco líneas horizontales paralelas. El tiempo transcurre a todo
lo largo de esas cinco líneas. Las alturas tonales de los instrumentos se representan con figuras musicales
emplazadas a diversas alturas utilizando como referencia las líneas del pentagrama y sobre todo una de
ellas: la línea dónde se situa la clave del pentagrama; un símbolo que determina la altura tonal de la figura
ubicada en dicha línea. Los demás valores de tono se determinan por la distancia
relativa de cada figura a la línea base o de clave. (Figura 3.2.1)
Además de especificar la altura tonal, se necesita saber durante cuánto tiempo se va a mantener.
Esto se resuelve asignando una figura distinta según la duración. (Figura 3.2.2).
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.4
Figura 3.2.2: Figuras m usicales y su duración relativa.
Estas duraciones son relativas a la duración total de una redonda. Para obtener duraciones mayores
se usa un símbolo llamado ligadura que une a dos o más figuras y hace que el sonido de cada una de ellas
sea contínuo a lo largo de la ligadura; en cambio, no hay un símbolo que permita establecer una duración
menor que la semifusa.
Además de la ligadura existen más símbolos que modifican la duración de una nota. Estas son el
puntillo y el calderón.
El puntillo es un pequeño punto que colocado a la derecha de una nota aumenta en media vez la duración
original de ésta.
El calderón es un símbolo que se coloca encima de la nota, fuera del pentagrama y modifica la duración
de la nota en un valor a libre juicio del intérprete.
Los tiempos se marcan en el pentagrama mediante compases. Son marcas en el pentagrama que
lo dividen en porciones de tiempo de igual duración cada una. La duración de cada compás (medida en
figuras musicales) viene dada por una fracción escrita al lado de la clave. El numerador indica cuántas
figuras entran en el compás y el denominador la figura que es. (Figura 3.2.3).
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.5
Figura 3.2.3: Ejem plo de pentagram a con dos com pases. Uso del puntillo y el calderón.
Para establecer la duración de referencia se suele indicar de la manera: figura = valor dónde
figura es el símbolo de la figura sobre la cual se va a aplicar la duración de referencia (puede ser
cualquiera ya que las duraciones de todas las figuras están relacionadas), y valor es el número de figuras
que van a entrar en un minuto de ejecución.
Otras veces, en lugar de utilizar esta nomenclatura se usa otra más ambigua que establece no la
duración individual de las figuras sino el ritmo o "tempo" de la pieza musical. Para describir este ritmo
se usan términos italianos como Presto, Allegro, Andante, Adagio, etc...
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.6
Figura 3.2.4. Ejemplo de partitura real.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.7
3.3.- Los secuenciadores. El formato .MOD
Ya que el lenguaje musical es demasiado ambiguo para poder ser interpretado con un ordenador,
es necesaria una formalización del mismo aunque sea a costa de perder naturalidad en la interpretación.
Un lenguaje de composición musical apto para ser usado en un sistema informático debe tener
las características que se le piden a un lenguaje de programación: exacto, flexible y falto de ambigüedades.
Los elementos de este lenguaje serán instrumentos, notas, tiempos, así como los parámetros que
pueden variarlos.
Pero este lenguaje no debe ser muy distinto del lenguaje de la partitura, que sigue siendo el
lenguaje universal de composición, y aún hoy tiene más potencia creativa que los lenguajes adaptados
a la informática.
Una vez definido, se llama secuenciador al sistema que es capaz de interpretar ese lenguaje. La
interpretación no tiene por qué significar una ejecución de la pieza en tiempo real. Puede ser una
traducción de éste a otro lenguaje, una representación del lenguaje en forma gráfica usando los símbolos
de la partitura, o un editor que permite la composición musical.
Además, el lenguaje de composición usado en un secuenciador puede ser invisible al usuario, que
puede seguir manejando los símbolos tradicionales, teniendo en cuenta las limitaciones que imponga el
lenguaje subyacente. De este modo, se pueden usar partituras en sistemas informáticos como archivos
de intercambio de datos entre distintos lenguajes de composición.
El estándar industrial en cuanto a estos lenguajes es el MIDI (Musical Instrument Data Interface).
Este estándar define una serie de pistas que son asignadas cada una a un instrumento. Las pistas se
interpretan paralelamente a lo largo del tiempo como si cada una fuera una parte de la partitura (un score).
Cada pista contiene una lista de notas, y los instantes de tiempo en que hay que tocarlas. Cada nota
tiene varios atributos: su duración, su tono, su volúmen son los principales. Además existen otros valores
que afectan a uno o varios parámetros de las notas que se están tocando en una pista como la modulación
(pitch blend), el vibrato y el trémolo.
La norma MIDI además define un tipo de conexión y formato específicos para intercambiar
información desde o hacia un instrumento musical. La configuración susal en un entorno MIDI consiste
en un teclado sintetizador y un ordenador. Aquí, tanto el teclado como el ordenador actúan de
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.8
secuenciador. El compositor toca la pieza en el teclado y vía MIDI se graba en la memoria del ordenador.
Ya después, con un programa de edición se retoca la partitura, se repiten pasajes que no se grabaron o
se mezcla la composición actual con otras ya grabadas. El resultado se puede reenviar al teclado que
interpreta los comandos MIDI desde el ordenador y los ejecuta en su sintetizador como si se estuviese
tocando con el teclado en ese momento.
Con el auge de la informática personal y la multimedia, cada vez es más corriente integrar en el
sistema informático dos de las tres tareas de la secuenciación: la edición y la interpretación, quedando
la conexión MIDI en un solo sentido, desde un terclado externo, más cómodo para tocar que el de un
ordenador, hacia el sistema.
La primera gran revolución en el campo de la música digital para ordenadores personales vino de
la mano de la empresa Commodore, que en su modelo Commodore 64 integraba un más que respetable
chip sintetizador, el SID. Opcionalmente el C64 disponía de un conector MIDI que gestionaba dicho
integrado, por lo que tenía acceso a gran cantidad de piezas escritas usando este lenguaje. Hasta entonces,
y aún después, la inclusión de la conexión MIDI era algo que a lo sumo se consideraba opcional dentro
de la configuración de un ordenador personal. De todas maneras, el SID no podía usarse para fines
profesionales dada su baja calidad relativa (si exceptuamos al grupo Mecano, ¡que usó un C64 en la
grabación de su primer disco!).
Para la segunda generación de ordenadores “espectaculares” de que hacía gala Commodore se
pensó en un hardware de audio más sofisticado y flexible que el anterior, todo ello embebido en una
arquitectura que perseguía el mayor paralelismo posible entre operaciones y todo ello gobernado por la
naciente (para los equipos personales) tecnología de 32 bits. Así se desarrolló el Amiga, y su integrado
generador de formas de onda complejas 8364.
En el Amiga también era fácil añadir un conector MIDI, y de hecho se usó con más asiduidad que
en el C64. Sin embargo lo peculiar de su arquitectura de generación de sonidos hizo más popular un
determinado formato de fichero cuyo contenido está intimamente ligado al hardware de dicho sistema.
Este formato es el Sound Tracker Module Music o más comunmente llamado MOD. Fue un
formato ideado por los mismos programadores del Sound Tracker, que lo incorporaban como opción a
la hora de grabar una composición escrita con él, aunque el formato por defecto era el de “song”. La razón
de que el MOD se implantase sobre el “song” fue principalmente porque aquél incorporaba toda la
información de los instrumentos muestreados en el mismo fichero lo que hacía más fácil la carga de los
mismos, sintener que estar cambiando de disco para leer cada instrumento. Hay que recordar que los
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.9
primeros Amiga 1000 y 500 se vendían sin disco duro, y la ampliación para disponer de uno era bastante
cara.
Las características técnicas de un fichero MOD son las siguientes:
L
4 canales o pistas de sonido simultáneos. Cada canal puede interpretar cualquier nota
dentro del rango disponible y con el instrumento que se desee de los que disponga el módulo.
L
El rango de notas cubre 3 octavas completas.
L
La frecuencia de muestreo de cada canal varía con la nota que se está tocando, y puede
llegar hasta los 28Khz.
L
Las 4 pistas se dividen en partes de igual longitud llamadas patrones. Cada patrón se
divide en 64 divisiones. Cada división puede contener una nota, un código de instrumento y un
efecto para aplicar sobre esa nota. Una división se divide en ticks, y el número de ticks por
división es variable, y se puede modificar con uno de los efectos. La duración de un tick es fija
y corresponde a 20ms. Por defecto se asumen 6 ticks por división, que corresponden a 125bpm
(un bpm corresponde a 4 divisiones).
L
Cada módulo puede definir hasta 31 instrumentos. Cada instrumento es una muestra
PCM de hasta 128K de longitud.
L
Puede haber hasta 64 patrones distintos en un módulo numerados del 0 al 63. El orden de
ejecución de los patrones dentro del módulo lo lleva una lista de patrones de hasta 128 bytes.
Cada elemento es el número del patrón que debe interpretarse a continuación.
Como aplicación principal de este trabajo, se desarrollará un programa que usando el hardware
del PC consiga emular el comportamiento del 8364 y aplicarlo a la interpretación de un fichero con estas
características usando como sintetizador un sistema hard externo al PC conectado por el puerto paralelo.
A continuación se describe el formato de un fichero .MOD (versión 2.0 de la especificación). Los
valores de 16 bits se codifican en el formato Motorola (primero el MSB).
20 bytes.
Título del módulo relleno con bytes \0 a la derecha.
La siguiente secuencia se repite 31 veces: una para cada instrumento
22 bytes.
Nombre de la muestra que representa al instrumento rellena con \0. Si un
nombre empieza con el caracter ‘#’ se asume que es un comentario del autor, entonces
los demás parámetros no se cuentan.
2 bytes.
Longitud de la muestra en palabras de 16 bits. Una longitud igual a 1 se
considera una muestra vacía.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.10
1 byte.
Los cuatro bits menos significativos representan un número en
complemento a 2 (-8 a 7) que indica el tono de la muestra. No se usará en la
simulación.
1 byte.
Volumen de la muestra entre 0 y 64.
2 bytes.
Comienzo del bucle de repetición en palabra de 16 bits. Este valor apunta
a la dirección de memoria dentro de la muestra desde la cual se realizará el looping de
la misma. El looping de una muestra consiste en la repetición de un bloque de la misma
una vez que se ha ejecutado entera la primera vez. De esta manera se pueden
implementar instrumentos con la duración que el compositor quiera.
2 bytes.
Longitud del bucle de repetición en palabras. El bucle existe si este valor
es mayor que 1.
1 byte.
Longitud de la secuencia de patrones. Desde 1 hasta 128.
1 byte.
Valor=127. Se puede ignorar.
128 bytes. Secuencia de patrones. Cada elemento de esta secuencia es un número de 0
a 63 que identifica el patrón que hay que tocar en ese momento. El valor máximo almacenado
en esta tabla es el número de patrón más alto que existe.
4 bytes.
Las iniciales M.K. Estas son las iniciales de Unknown/D.O.C quien cambió el
formato para adaptarlo a 31 instrumentos. El formato antiguo no tenía este campo.
Algunos programas secuenciadores usan este campo para incluir información adicional. Por
ejemplo:
FLT4 o FLT8:
usado por el programa Startrekker para indicar 4 u 8 canales.
M!K!:
usado por Protracker para indicar que hay más de 64 patrones.
6CHN o 8CHN:
también identifica un módulo de 6 u 8 canales en Protracker.
A continuación se almacenan los patrones.Cada patrón ocupa 1024 bytes, divididos en
64 divisiones que ocupan cada una 16 bytes. Dentro de cada división están los datos para
cada uno de los 4 canales, ocupando cada canal 4 bytes en una división. El formato de la
información en cada canal es la siguiente:
Si este nibble vale 1, se suma 16 al
campo ‘instrumento’
Byte 0
Valor de la nota
Instrumento
Byte 1
Byte 2
Efecto
Parámetros del efecto
Byte 3
El primer MSN (Most Significant Nibble) del byte 0 normalmente contiene el valor 0, pero
al hacer la ampliación a 31 instrumentos se usó como bit 4 del campo instrumento.
El valor de la nota es un campo de 12 bits que ocupa el LSN (Least Significant Nibble)
del byte 0 y el byte 1. Este valor es el que habría que cargar en el contador del 8364 para
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.11
generar la frecuencia de muestreo requerida para tocar la nota a un determinado tono. Por
ejemplo: si hemos muestreado un DO de un piano a 8272 Hz, para escuchar ese mismo DO
hay que cargar el valor 214d en el contador del 8364. Si en lugar de este valor ponemos, por
ejemplo, un 190d, la muestra se leerá más rapidamente, y el tono resultante será un RE.
Para nosotros este valor no tiene significado en sí mismo, sino que lo usaremos como
índice a una tabla donde estarán los valores de la “recta” generada con el algoritmo de
Bresenham apropiados para emular el tono.
Los valores de frecuencia usados en los MOD’s estándar cubren 3 octavas. Algunas
versiones cubren 2 octavas más, una por encima y otra por debajo de las normales. Los
valores del campo ‘nota’ para cada nota y octava son estos:
DO
DO#
RE
RE#
MI
FA
FA#
SOL
SOL#
LA
LA#
SI
Octava 1
856
808
762
720
678
640
604
570
538
508
480
453
Octava 2
428
404
381
360
339
320
302
285
269
254
240
226
Octava 3
214
202
190
180
170
160
151
143
135
127
120
113
Octava 0
1712
1616
1525
1440
1357
1281
1209
1141
1077
1017
961
907
Octava 4
107
101
95
90
85
80
76
71
67
64
60
57
EL MSN del byte 2 contiene los 4 bits bajos del campo ‘instrumento’. El campo completo
ocupa 5 bits, con lo que se admiten hasta 32 instrumentos distintos, pero el valor 0 está
reservado para indicar ‘no instrumento’. Si hay un valor válido en el campo nota pero
instrumento vale 0, indica que esa nota debe tocarse con el último instrumento válido en ese
canal. No se admite que la primera nota que aparece en un módulo tenga instrumento 0.
El LSN de este mismo byte contiene un valor del 0 al 15 que determina el tipo de efecto
a aplicar sobre la nota. El byte 3 contiene los parámetros (si los necesita) del efecto. Un valor
de 0 en estos dos campos indica ‘no hay efecto’.
A continuación se describen los efectos soportados en la emulación. Para una
enumeración completa de los efectos soportados por la versión 2.0 consultar la bibliografía.
0:
Arpeggio. El parámetro se divide en dos nibbles: A y B. Este efecto consiste en tocar
la nota normalmente, después se toca esa misma nota pero añadiéndole A semitonos, y
después se vuelve a tocar añadiéndole B semitonos. Estas fluctuaciones de tono se realizan
a intervalos regulares de tiempo dentro de una división.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 3.12
1:
Slide up. Decrementa el período de la nota por lo que su tono se incrementa
suavemente. El valor del decremento lo da el parámetro. La operación se hace en cada tick,
y mientras no se encuentre otra nota en el mismo canal. Nótese que lo que se decrementa es
el valor del período (lo que se carga en los contadores del 8364). No se puede subir el tono
de
2:
Slide down. Incrementa el período de la muestra, bajando su tono. Actúa de manera
análoga al efecto anterior.
3:
Slide to note. Cambia el tono del instrumento actual desde la nota que se está oyendo
en ese momento hasta la nota que acompaña a este efecto. La suavidad del cambio
dependerá, como en los dos casos anteriores, del parámetro. La dirección del cambio está
implícita por la nota inicial y final. Si el parámetro es 0, se continua con los valores del último
efecto 3 en ese canal.
9:
Offset. Toca el instrumento asignado a esta nota a partir de la posición parámetro*256d.. Este desplazamiento se mide en palabras.
10:
Volume slide. El parámetro se toma como dos nibbles. Si el niblle superior A es distinto
de 0 se sube el volúmen A unidades en cada tick. Si el nibble inferior B es distinto de 0 y el
superior es igual a 0, se baja el volúmen B unidades por cada tick. El cambio no puede pasar
el rango de volúmen: 0 a 64.
11:
Salto. El patrón entero (los 4 canales) se parará después de ejecutada la actual
división, y la p'roxima división a leer será la primera división del patrón que indique el
parámetro.
12:
Poner volumen. Asigna el volumen especificado por el parámetro al instrumento actual
en la nota correspondiente a esta división.
13:
Acabar patrón. Análogo al comando 11 salvo que el patrón que se lee es el siguiente.
En la simulación no se ha tenido en cuenta el parámetro, que indica a partir de qué división se
empieza a leer el patrón.
Efectos tipo 14. Son una serie de efectos codificados con dos números. El primero es siempre
14 y se almacena en el lugar del tipo de efecto, como es susal. El segundo número es el MSN
del parámetro. Por tanto, los parámetros se almacenan en el LSN del byte asignado al campo
‘parámetro’.
De ellos sólo se han implementado dos: el efecto 10 y el efecto 11. Son, respectivamente, fine
volume slide up y fine volume slide down. El efecto consiste en subir o bajar el volúmen tantas
unidades como indique el parámetro, pero sólo una vez al principio de la división (tick 0).
15:
Velocidad. El parámetro indica el número de ticks que tendrá una división a partir de
ahora, si éste es menor que 32. Si es mayor o igual, indica los bpm (beats por minuto) con que
se ejecutará el módulo. Sólo se ha implementado la opción menor que 32.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.1
4. ESTUDIO DE LA VIABILIDAD DE LA
EMULACION EN UN PC AT 386
Después de haber descrito en el capítulo 2 el hardware dedicado al sonido del Amiga, se procederá
al estudio de viabilidad de la emulación de dicho hardware, usando los recursos que a continuación se
exponen. Para cada componente se dará una descripción general del mismo, su función dentro del sistema
y la manera en que puede ser útil en la simulación [INTEL]
4.1.- El temporizador programable 8254.
El 8254 es un timer de propósito general. Es programable por el usuario y dispone de 3 contadores
independientes que, en el caso del PC, tienen común su señal de reloj, de aproximadamente 1,193 Mhz.
Cada uno de ellos está asignado a una parte del sistema. El contador 0 es el más importante para
nuestra tarea, ya que es el único que puede generar interrupciones a la CPU. Normalmente éstas ocurren
unas 18,2 veces por segundo y se usan para actualizar el reloj del sistema y apagar los motores de las
disqueteras al cabo de un cierto time-out desde su última utilización.
El contador 1 se suele usar para el refresco de la RAM, aunque en los sistemas AT esto no
siempre es así, sino que hay una lógica dedicada a esta tarea.
El contador 2 se puede usar como contador del usuario, o bien permite generar tonos por el
altavoz programándolo para que genere señales cuadradas.
El 8254 tiene 5 modos de funcionamiento, pudiendo estar cada contador en cualquiera de éstos:
X
Modo 0: Interrupción con la finalización de una cuenta.
X
Modo 1: Monoestable redisparable por hardware.
X
Modo 2: Generador de frecuencias.
X
Modo 3: Generación de onda cuadrada.
X
Modo 4: Pulso disparado por software.
X
Modo 5: Pulso disparado por hardware.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.2
La programación se hace de la siguiente manera:
Puerto 43h
SC1
SC0
RW1
RW0
D7
D6
D5
D4
M2
D3
M1
M0
D2
D1
BCD (norm. 0)
D0
SC - Select Counter (seleccionar contador)
SC1
SC0
0
0
Seleccionar contador 0 (puerto 40h)
0
1
Seleccionar contador 1 (puerto 41h)
1
0
Seleccionar contador 2 (puerto 42h)
1
1
Comando read-back
M - Modo
M2 M1 M0
0
0
0
Modo 0
0
0
1
Modo 1
X
1
0
Modo 2
X
1
1
Modo 3
1
0
0
Modo 4
1
0
1
Modo 5
RW - Read/Write
RW1 RW0
0
0
Comando de almacenamiento del contador.
0
1
Leer/escribir sólo LSB
1
0
Leer/escribir sólo MSB
1
1
Leer/escribir LSB y después MSB
Así, para programar al timer para que genere 1000 interrupciones por segundo, se procederá de
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.3
la siguiente manera:
reloj
equ 1193180
mov
out
mov
out
mov
out
al,00110100b
43h,al
ax,reloj/1000
40h,al
al,ah
40h,al
Como se puede observar, se puede usar esta característica del 8254 para “simular” la DMA del
Amiga, haciendo transferencias por interrupciones. La rutina que se encargará de hacer 1 trasvase de la
memoria al dispositivo DAC se ubicará en la int 08h.
Hay que hacer notar que cualquier rutina que use este servicio debe encargarse de llamar a la
antigua int 08h con la misma frecuencia que tenía antes, esto es, 18,2 Hz, si se va a usar la aplicación en
background.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.4
4.2.- El controlador programable de interrupciones 8259A.
Se usa este circuito para gestionar y priorizar las diferentes fuentes de interrupción del sistema.
Sirve, por tanto, como interfaz entre la CPU y los periféricos. En el AT hay dos de estos controladores,
pero nos centraremos en el primero, y sobre todo en dos de sus lineas de interrupción.
La inicialización del 8259 escapa al propósito de este epígrafe, así que se supondrá un entorno
de sistema PC en el cual la BIOS se ha encargado de todas estas tareas.
De este modo, el 8259 está configurado para 6 lineas de interrupción de sus 7 posibles (la linea
2 está conectada en realidad a un segundo controlador). De ellas, la linea 0 corresponde a la interrupción
del timer, y la linea 7 (y/o 5) está dedicada a la interrupción generada por el puerto paralelo.
Cada linea de interrupción puede enmascararse a voluntad. Para ello se emplea el puerto 21h
desde el que se pueden consultar o modificar los permisos de interrupción de cada linea.
I7
I6
I5
I4
I3
I2
I1
I0
Interrupt Mask Register (puerto 21h)
Un 0 indica que la interrupción está habilitada, y un 1 indica que está deshabilitada.
Cuando se está atendiendo una interrupción, el 8259 bloquea cualquier otra petición de
interrupción de la misma o de inferior prioridad. Para indicar que una interrupción ha sido atendida, se
ha de mandar un comando de EOI (End Of Interrupt) por el puerto 20h. El comando EOI es el 20h.
Así, para nuestros propósitos sólo necesitaremos saber cómo habilitar y deshabilitar interrupciones, y cómo decirle al controlador que hemos acabado la gestión de una. Entonces, una posible rutina de
gestión de interrupciones sería:
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.5
interrupc proc far
pushad
;guardamos todos los registros generales
push ds
mov ax,dgroup
mov ds,ax
;apuntamos a nuestras variables globales
call gestion_interrupcion
mov al,20h
out 20h,al
;mandar un EOI
pop ds
popad
iret
;fin de la interrupción
interrupc endp
Como después se verá, interesa que la duración de esta rutina sea la menor posible, sobre todo si
la interrupción va a suceder muchas veces por segundo.
Como el entorno de programación es MS DOS, hay que tener en cuenta que no se pueden (por
lo general) hacer llamadas a funciones del sistema desde dentro de una rutina de servicio de interrupciones porque la interrupción puede haber ocurrido durante el procesamiento de una llamada al sistema, y
MS DOS no es reentrante. Esto restringirá las acciones que se pueden desarrollar en el gestor, y que
obligará en algunos casos a usar el hard directamente, en lugar de los servicios de la BIOS o del DOS.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.6
4.3.- El puerto paralelo.
En el 8364, una vez que los datos han sido leidos por los canales de DMA son enviados a los
DAC’s de 8 bits que en definitiva son los responsables de la generación del sonido. En el PC, por contra,
no se dispone de ningún dispositivo estándar análogo a los conversores digital-analógico de que dispone
el Amiga. A diferencia de otros micros de su época, el PC fue el único ordenador que salió peor parado
en este aspecto.
La solución propuesta es usar el puerto paralelo. Este dispositivo consta de un bus de 8 bits con
señales de handshaking para comunicar datos desde el sistema hacia una impresora. El usuario puede
cambiar libremente el contenido del bus y actuar sobre las lineas de protocolo de la manera más
conveniente. Se dispone de lineas de entrada desde las que se puede examinar el estado de la impresora.
Una de estas líneas (ACK) está configurada para poder generar una interrupción al 8259.
Externamente consta de un conector D25 hembra con el siguiente patillaje:
Nº
Nombre
Sentido
Función
1
STROBE
SALIDA
2
D0
ENTRADA/SALIDA
3
D1
ENTRADA/SALIDA
4
D2
ENTRADA/SALIDA
5
D3
ENTRADA/SALIDA
6
D4
ENTRADA/SALIDA
7
D5
ENTRADA/SALIDA
8
D6
ENTRADA/SALIDA
9
D7
ENTRADA/SALIDA
10
ACK
ENTRADA
Indica al ordenador que los datos han sido leídos
11
BUSY
ENTRADA
Indica al ordenador que la impresora está ocupada y no puede leer datos
12
PAPER OUT
ENTRADA
Indica al ordenador que falta papel
13
SELECT
ENTRADA
Indica al ordenador que la impresora está ON-LINE
14
AUTO FEED
SALIDA
Indica a la impresora que debe hacer un avance de linea
15
ERROR
ENTRADA
Indica al ordenador que ha ocurrido un error
16
RESET
SALIDA
Inicializa la impresora
17
SELECT INPUT
SALIDA
Indica a la impresora que el puerto está operativo
GND
MASA DE SEÑAL
18-25
Indica a la impresora que hay datos válidos en el puerto
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.7
Se pueden configurar hasta tres puertos paralelos, conocidos bajo DOS como LPT1, LPT2 y
LPT3.
La programación de cada puerto está a cargo de 3 registros, asignados de la siguiente manera:
Puerto
Datos
Estado
Control
LPT1
3BCh
3BDh
3BEh
LPT2
378h
379h
37Ah
LPT3
278h
279h
27Ah
El formato de cada registro es el siguiente:
Puerto 3BCh, 378h, 278h (lectura/escritura)
D7
D6
D5
D4
D3
D2
D1
D0
Puerto de datos. Cada bit corresponde a un bit del bus de datos del puerto paralelo.
Puerto 3BDh, 379h, 279h (sólo lectura)
BUSY\
ACK\
OUT OF PAPER
BUSY:
ONLINE
ERROR
no usada
no usada
TIME OUT
0=im presora no ocupada
1=im presora ocupada
ACK:
0=no se han recibido datos
1=datos recibidos satisfactoriam ente
OUT OF PAPER:
0=no se ha llegado al fin del papel
1=se ha llegado al fin del papel
ON LINE
0=la im presora está en off-line
1=la im presora está en on-line
ERROR:
0=no error
1=error
TIME OUT:
0=no hay tim e-out
1=se llegó al tim e-out
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.8
Puerto 3BEh, 37Ah, 27Ah (lectura/escritura)
no usada
no usada
DIR
DIR:
IRQ_EN
SELECT INPUT
RESET\
AUTO LINE FEED
STROBE\
0=sentido de los datos desde el ordenador a la im presora
1=sentido de los datos desde la im presora al ordenador
IRQ_EN:
0=deshabilita IRQ 5/7 para ACK
1=habilita IRQ 5/7 para ACK
SELECT INPUT
0=puerto no preparado
1=puerto preparado
RESET:
0=inicializar im presora
AUTO LINE FEED:
0=no hacer avance de linea
1=funcionam iento norm al
1=hacer avance de linea
STROBE:
0=no hay datos en el bus
1=hay datos en el bus
Lo importante de este dispositivo es que podemos poner cualquier dato en el bus y manejar a
nuestra voluntad las lineas de control, de forma que podemos acoplar cualquier dispositivo que queramos
que lea datos de 8 bits escritos por el ordenador. Asímismo, otro dispositivo puede ofrecer datos a través
de este mismo puerto y avisarnos de que están listos usando la linea ACK.
En este proyecto se usará el puerto paralelo como un mini bus ISA, con las señales de protocolo
indispensables para poder manejar cuatro dispositivos. Tres de ellos de escritura y uno de lectura. Las
cuatro lineas del puerto de control proporcionarán el acceso a cualquiera de ellos. Los detalles del montaje
se verán en el capítulo 6. En los apartados siguientes se supondrá la existencia de un dispositivo
conectado directamente al bus del puerto paralelo, sin uso de protocolos.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.9
4.4.- Ejecución en background. Degradación del rendimiento del
sistema.
El propósito del análisis de los dispositivos descritos hasta ahora no es sino ofrecer una alternativa
viable a la transferencia DMA de un bloque de datos a un ritmo seleccionado, hacia un dispositivo de E/S
en un sistema que carece de estas características.
Se ha descrito a lo largo de este capítulo cómo una gestión por interrupciones puede solucionar
el problema. Sin embargo, esta gestión debe ser lo más eficaz posible, ya que, a diferencia del DMA, es
la CPU la que debe hacer el trasvase e datos interrumpiendo la tarea que está haciendo.
Además la tasa de transferencia de datos debe ser lo suficientemente alta como para proporcionar
un sonido de calidad aceptable. Esto supone no menos de 22050 transferencias por segundo (como se vio
en el cap. 2, el 8364 llega hasta alrededor de 28000 transferencias por segundo). Esto por supuesto, con
la posibilidad de poder hacer otra tarea en primer plano mientras se lleva a cabo el trasvase.
Es por esto que se debe estudiar los tiempos de ejecución de la rutina de servicio de interrupciones
para estimar la sobrecarga del sistema impuesta por la simulación.
En la figura siguiente se ha representado un gráfico del tiempo de utilización de la CPU por dos
tareas: la tarea del sistema, que es todo aquello que percibimos como trabajo activo de la CPU (el S.O.,
un procesador de textos, etc...) Y que se debe ejecutar en primer plano, y la tarea de la interrupción del
timer que debe ser invisible al usuario.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.10
En esta situación llamaremos Tefec al tiempo del que dispone la tarea del sistema, y Tint al
tiempo del que dispone la rutina de servicio de la interrupción. Entonces, el porcentaje de sobrecarga, H,
será:
Donde Tint+Tefec debe ser igual al intervalo entre dos peticiones de interrupción, que será
inversamente proporcional a la frecuencia de muestreo elegida para reproducir el sonido digitalizado.
Se debe tener en cuenta que éste es un caso ideal. En la realidad hay otras fuentes de interrupción
que también deben ser atendidas, y que restan tiempo del asignado en principio a la tarea del sistema. Esta
misma puede perjudicar a la respuesta de la rutina de interrupción si ejecuta zonas de código en las que
se desactiven las interrupciones. Aún así el esquema propuesto es suficientemente aproximado para
aplicarlo a nuestro caso particular.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.11
4.5.- Prueba de emulación de un canal digital por el puerto
paralelo.
En esta sección se describirá una primera aproximación a lo que llegará después a ser la rutina
principal de ejecución de los MOD’s. El objetivo de la rutina que se desarrolle será enviar un bloque cuya
dirección lejana está en p, de n bytes de longitud, siendo n<64K por el puerto paralelo con base en la
dirección 378h, y a una frecuencia de reproducción f medida en herzios.
Se supondrá un sistema DMA sin autoinicialización (los cambios que hay que hacer en el fuente
para conseguir la autoinicialización son triviales). Se debe disponer de una señal, flag o similar para saber
cuándo ha acabado la transferencia, que en nuestro caso será una variable global FinDMA, que valdrá
1 si se llegó al final de la cuenta, y 0 si no.
El contenido del archivo de cabecera para este conjunto de rutinas es el siguiente:
extern char FinDMA;
void IniciaDMA (char *p, unsigned n, unsigned f);
void DetieneDMA (void);
Y el fuente de las rutinas es éste:
.286
; Usaremos el juego de instrucciones del 80286
.model large
; Para compilar con un programa en C usando el modelo large
.data
AnteriorInt08
PosicionActual
ContadorDMA
CuentaTimer
ContadorTimer
FinDMA
dd
dd
dw
dw
dw
0
0
0
0
0
;
;
;
;
;
;
db 0
;
public C FinDMA
Antiguo vector de la int 08h
Registro de dirección actual
Contador de bytes que quedan por enviar
Número de pulsos que debe contar el siguiente contador
Contador de pulsos hasta la siguiente
llamada a la antigua int 08h
Flag de fin de transferencia
.code
public C IniciaDMA
public C DetieneDMA
IniciaDMA
proc C p:ptr byte, n:word, f:word
cli
; Sin interrupciones durante la inicialización
push es
push si
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.12
les si,p
mov word ptr PosicionActual,si
mov word ptr PosicionActual+2,es
mov ax,n
mov ContadorDMA,ax
mov ax,3508h
int 21h
; Función: obtener vector de interrupción
; de número AL en ES:BX
mov word AnteriorInt08,bx
mov word ptr AnteriorInt08+2,es
push ds
mov dx,offset NuevaInt08
mov ax,seg NuevaInt08
mov ds,ax
mov ax,2508h
int 21h
; Función: asignar rutina de servicio de
; la interrupción de número AL al código
; apuntado por DS:DX
pop ds
mov al,00110110b
out 43h,al
mov dx,0012h
mov ax,34DCh
mov bx,f
div bx
push ax
out 40h,al
mov al,ah
out 40h,al
pop bx
xor dx,dx
mov ax,65535
div bx
IniciaDMA
DetieneDMA
mov
mov
mov
pop
pop
sti
ret
endp
; Contador 0, modo 3
; DX:AX=001234DCh=1193180d
; AX=int(1193180/f)
; Ahora el timer genera una señal de f Hz
; DX=0
; AX=pulsos que hay que conar antes de
; llamar a la antigua int 08h
CuentaTimer,ax
ContadorTimer,0
FinDMA,0
si
es
; Empieza la transferencia en background
proc C
cli
xor al,al
out 40h,al
jmp $+2
; Restauramos antiguo valor del timer 0
; Un pequeño retraso para que el 8254 tenga
; tiempo de leer el dato
out 40h,al
push ds
lds dx,AnteriorInt08
mov ax,2508h
; Restauramos antigua rutina de la int 08
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.13
int 21h
pop ds
DetieneDMA
NuevaInt08
mov FinDMA,1
sti
ret
endp
proc
push
push
push
push
push
; Señala el fin de la transferencia DMA
far
ax
dx
si
ds
es
mov ax,dgroup
mov ds,ax
; Señalamos DS al segmento de datos de C
cmp FinDMA,1
je PulsoIdle
; Hay más datos por transferir?
; Si no, vete al final
les
mov
mov
out
inc
dec
jnz
mov
si,PosicionActual
dx,378h
al,es:[si]
; Lee la muestra actual
dx,al
; y la manda al puerto paralelo
word ptr PosicionActual
ContadorDMA
; Actualiza contador DMA
PulsoIdle
; Si terminó la transferencia
FinDMA,1
; notifícalo
PulsoIdle:
inc ContadorTimer
; Contar pulso
mov ax,ContadorTimer
cmp ax,CuentaTimer
; ¿es hora de llamar al reloj?
jne FinalInt08
mov ContadorTimer,0
pushf
call dword ptr AnteriorInt08
; Simulamos una llamada a interrupción
FinalInt08:
mov al,20h
out 20h,al
pop es
pop ds
pop si
pop dx
pop ax
iret
endp
NuevaInt08
; Mandar EOI al 8259
end
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.14
4.5.- Reproducción de varios canales digitales
Hasta ahora, la emulación de un canal de DMA con las mismas características de las que se
dispone en el 8364 no ha sido difícil. El problema aparece cuando son 4 los canales DMA a emular. Cada
canal tiene su propio contador que le permite muestrear a distintas frecuencias. De esta manera se pueden
interpretar cuatro notas a un tiempo.
Si embargo, en el PC sólo disponemos de un timer para emular un canal DMA a una determinada
frecuencia. La solución más inmediata consiste en tener un contador para cada canal que cuente ticks de
interrupción y haga la transferencia cuando se haya llegado al final de la cuenta, pero ello requeriría hacer
funcionar al timer del PC a una frecuencia muy alta respecto de la máxima frecuencia a usar realmente,
por lo que la sobrecarga del sistema sería mayor, y la mayoría de los ticks de interrupción no harían nada
útil; sólo contar.
En la figura 4.1 se puede observar la idea que subyace a la solución elegida. Dependiendo de la
pendiente de la recta, la gráfica de la señal resultante está más estirada o comprimida que la original. De
esta manera es como se controla el pitch o tono de la muestra resultante que será igual a la frecuencia de
la muestra original multiplicada por la pendiente de la recta usada en la transformación.
Figura 4.6.1. Muestreo de una señal usando Bresenham
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.15
La idea es, pues, la siguiente: partiendo de su pendiente, se puede construir una recta de N puntos,
donde N es la longitud de la muestra, siguiendo el algoritmo de Bresenham. Este algoritmo lo
modificaremos para que nos dé los incrementos de la coordenada Y en lugar del punto resultante.
Así, para una recta horizontal (pendiente=0) el algoritmo nos devolvería una secuencia como
0,0,0,0,0,...,0 porque la coordenada Y nunca cambia.
Si la pendiente es 1, tenemos una diagonal en el primer cuadrante. En este caso, la coordenada
Y se incrementa con cada paso de la X. La secuencia sería: 1,1,1,1,...,1.
Si la pendiente fuera 1/2, la secuencia sería 1,0,1,0,1,0,1,0,1,0..... Intuitivamente se demuestra que
la pendiente es el valor medio de la sucesión obtenida.
Estos valores los usaremos a la hora de incrementar la dirección para obtener una nueva muestra.
En lugar de sumar siempre 1 y dejar que sea el timer quien marque el ritmo de la transferencia, haremos
que éste tenga una frecuencia fija igual a la máxima frecuencia de muestreo que se vaya a usar. Por cada
interrupción se van leyendo uno a uno los valores de la secuencia de incrementos proporcionada para la
nota que queremos tocar. Después de leer la muestra actual y enviarla al puerto paralelo, la dirección de
la siguiente muestra se calculará como la dirección de la actual+el valor del elemento leido de la
secuencia.
A continuación se lista el fuente del emulador de DMA desarrollado con este método. Esta vez
se aceptarán dos transferencias simultaneas de dos bloques de memoria ubicados en direcciones distintas,
de distinta longitud y con una frecuencia de muestreo diferente para cada uno. Las muestras leídas se
mezclarán digitalmente y el resultado será el que se envie al puerto paralelo. El listado se puede modificar
para que en lugar de ser 2 sean N los canales de DMA a emular.
Prototipos de las funciones
extern char FinDMACanal1;
extern char FinDMACanal2;
void IniciaDMA (char *p1, unsigned n1, char near *f1, char *p2, unsigned n2, char near *f2);
void DetieneDMA (char n);
Implementación
.286
; Usaremos el juego de instrucciones del 80286
.model large
; Para compilar con un programa en C usando el modelo large
.data
AnteriorInt08
dd 0
; Antiguo vector de la int 08h
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
PosicActCanal1
ContDMACanal1
PosicActCanal2
ContDMACanal2
BaseIncrCanal1
OffsetIncrCanal1
Muestra1
Muestra2
BaseIncrCanal2
OffsetIncrCanal2
CuentaTimer
ContadorTimer
FinDMACanal1
FinDMACanal2
dd
dw
dd
dw
dw
dw
Pag. 4.16
0
0
0
0
0
0
; Registro de dirección actual canal 1
; Contador de bytes que quedan por enviar canal 1
; Registro de dirección actual canal 2
; Contador de bytes que quedan por enviar canal 2
; Comienzo dentro de DS de la tabla de incrementos para el canal 1
; Indice que se mueve a lo largo de la tabla de incrementos
; del canal 1
dw 0
; Muestra del canal 1
dw 0
; Muestra del canal 2
dw 0
; Comienzo dentro de DS de la tabla de incrementos para el canal 2
dw 0
; Indice que se mueve a lo largo de la tabla de incrementos
; del canal 2
dw 0
; Número de pulsos que debe contar el siguiente contador
dw 0
; Contador de pulsos hasta la siguiente
; llamada a la antigua int 08h
db 0
; Flag de fin de transferencia canal 1
db 0
; Idem canal 2
public C FinDMACanal1
public C FinDMACanal2
.code
public C IniciaDMA
public C DetieneDMA
IniciaDMA
proc C p1:ptr byte, n1:word, f1:word, p2:ptr byte, n2:word, f2:word
cli
; Sin interrupciones durante la inicialización
push es
push si
les
mov
mov
les
mov
mov
si,p1
word ptr
word ptr
si,p2
word ptr
word ptr
mov
mov
mov
mov
ax,n1
ContDMACanal1,ax
ax,n2
ContDMACanal2,ax
mov
mov
mov
mov
ax,f1
BaseIncrCanal1,ax
ax,f2
BaseIncrCanal2,ax
PosicActCanal1,si
PosicActCanal1+2,es
PosicActCanal2,si
PosicActCanal2+2,es
mov ax,3508h
int 21h
; Función: obtener vector de interrupción
; de número AL en ES:BX
mov word AnteriorInt08,bx
mov word ptr AnteriorInt08+2,es
push ds
mov dx,offset NuevaInt08
mov ax,seg NuevaInt08
mov ds,ax
mov ax,2508h
int 21h
; Función: asignar rutina de servicio de
; la interrupción de número AL al código
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 4.17
; apuntado por DS:DX
pop ds
mov al,00110110b
out 43h,al
IniciaDMA
; Contador 0, modo 3
mov
out
mov
out
ax,001Bh
40h,al
al,ah
40h,al
mov
mov
mov
mov
mov
mov
CuentaTimer,097Bh
ContadorTimer,0
FinDMACanal1,0
FinDMACanal2,0
OffsetIncrCanal1,0
OffsetIncrCanal2,0
pop si
pop es
sti
ret
endp
; Aprox. 44100 Hz
; Ahora el timer genera una señal de 44100 Hz
; Ticks antes de llamar al reloj
; Empieza la transferencia en background
DetieneDMA
proc C n:byte
cmp n,1
jnz DetenCanal2
mov FinDMACanal1,1
cmp FinDMACanal2,1
jne CanalActivo
jmp ResetTimer
DetenCanal2:
mov FinDMACanal2,1
cmp FinDMACanal1,1
jne CanalActivo
ResetTimer:
cli
xor al,al
out 40h,al
jmp $+2
; Restauramos antiguo valor del timer 0
; Un pequeño retraso para que el 8254 tenga
; tiempo de leer el dato
out 40h,al
push ds
lds dx,AnteriorInt08
mov ax,2508h
; Restauramos antigua rutina de la int 08
int 21h
pop ds
CanalActivo:
DetieneDMA
NuevaInt08
sti
ret
endp
proc
push
push
push
push
push
push
far
ax
bx
dx
si
ds
es
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
mov ax,dgroup
mov ds,ax
NoDMA1:
NoDMA2:
; Señalamos DS al segmento de datos de C
cmp FinDMACanal1,1
je NoDMA1
call TransfDMACanal1
cmp FinDMACanal2,1
je NoDMA2
call TransfDMACanal2
mov
cbw
mov
mov
cbw
add
sar
mov
out
Pag. 4.18
; Hay más datos en canal 1?
; Si no, no hacer nada
; Hay más datos en canal 2?
; Si no, no hacer nada
al,Muestra1
; Lee y extiende el signo de la muestra 1 en AX
bx,ax
al,Muestra2
ax,bx
ax,1
dx,378h
dx,al
; Idem con la muestra 2
; Las mezcla
; obteniendo la señal resultante
; y la envía al puerto paralelo
inc ContadorTimer
; Contar pulso
mov ax,ContadorTimer
cmp ax,CuentaTimer
; ¿es hora de llamar al reloj?
jne FinalInt08
mov ContadorTimer,0
pushf
call dword ptr AnteriorInt08
; Simulamos una llamada a interrupción
FinalInt08:
NuevaInt08
TransfDMACanal1
mov al,20h
out 20h,al
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
endp
; Mandar EOI al 8259
proc near
les si,PosicActCanal1
mov al,es:[si]
mov Muestra1,al
mov
mov
mov
xor
; Lee la muestra actual
; y la almacena
bx,BaseIncrCanal1
di,OffsetIncrCanal1
al,[bx+di]
ah,ah
; AX=valor del incremento a
; sumar a la posición actual
add si,ax
; Lo suma
mov word ptr PosicActCanal1,si ; y lo almacena
inc byte ptr OffsetIncrCanal1 ; próximo valor de incremento. Cuando lleva 255 valores,
el próxinmo es 0
sub ContDMACanal1,ax
FinTransfDMA1:
jnz FinTransfDMA1
mov FinDMACanal1,1
mov Muestra1,0
ret
;
;
;
;
;
;
Decrementa el contador en la misma
cantidad que se ha incrementado el
puntero a la muestra actual
Si terminó la transferencia
notifícalo
este canal ya no cuenta en la mezcla
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
TransfDMACanal1
endp
TransfDMACanal2
proc near
les si,PosicActCanal2
mov al,es:[si]
mov Muestra2,al
mov
mov
mov
xor
Pag. 4.19
; Lee la muestra actual
; y la almacena
bx,BaseIncrCanal2
di,OffsetIncrCanal2
al,[bx+di]
ah,ah
; AX=valor del incremento a
; sumar a la posición actual
add si,ax
; Lo suma
mov word ptr PosicActCanal2,si ; y lo almacena
inc byte ptr OffsetIncrCanal2 ; próximo valor de incremento. Cuando lleva 255 valores,
el próxinmo es 0
sub ContDMACanal2,ax
FinTransfDMA2:
TransfDMACanal2
jnz FinTransfDMA2
mov FinDMACanal2,1
mov Muestra2,0
ret
endp
;
;
;
;
;
;
Decrementa el contador en la misma
cantidad que se ha incrementado el
puntero a la muestra actual
Si terminó la transferencia
notifícalo
este canal ya no cuenta en la mezcla
end
Se has escogido una frecuencia de muestreo máxima de 44100 Hz, con lo que las rectas que
necesitaremos tendrán pendiente menor o igual a 1. Los valores del algoritmo de Bresenham para cada
canal se guardarán en el área de variables globales, siendo f1 y f2 desplazamientos dentro de DS al
principio de cada secuencia. Cada valor de la secuencia es un byte con el valor 0 o 1; 0 si no hubo
incremento de Y, y 1 si lo hubo.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.1
5. EL MODO 32-BIT FLAT POINTER EN
MODO REAL O REALMEM.
5.1. El modo real y el modo protegido en un 80386.
A lo largo de este capítulo examinaremos algunos de los recursos que, en cuanto a gestión de
memoria, nos ofrece el 80386 bajo MS DOS.
Este sistema operativo se ejecuta en el llamado modo real de la CPU. En este modo, que es el que
tiene por defecto al resetearse, un 80386 se comporta basicamente como un 8086 muy rápido, al que se
le han añadido instrucciones y registros de 32 bits.
El esquema de direccionamiento de memoria es el que hereda de estos micros: 1 Mb de espacio
de direccionamiento, dividido en segmentos de 64K. De esta manera la memoria pasa de ser un vector
a ser un array bidimensional. Una posición queda determinada por dos coordenadas: segmento y
desplazamiento.
Este mecanismo era necesario ya que, por una parte el 8086 debía ser compatible (aunque sólo
fuera a nivel de código fuente) con sus predecesores 8085 y 8080 y esto implicaba limitaciones en el
ancho de palabra de la máquina; y por otra parte todavía no estaba extendido en los micros personales
el uso de los 32 bits. Así, el 8086 estaba restringido al uso de registros de 16 bits, con los cuales sólo se
puede direccionar hasta 64K en principio.
Por tanto la posición de un byte en la memoria se calcula como segmento*16+desplazamiento.
El hecho de multiplicar el valor del segmento por 16 equivale a desplazarlo 4 bits a la izquierda, con lo
que se convierte en un número de 20 bits. Entonces, cada valor del segmento representa una posición base
de memoria múltiplo de 16. El valor límite, 65535d (FFFFh), al multiplicarlo por 16 quedará como
FFFF0h o 1048560d.
El desplazamiento se suma sin más al valor anteriormente calculado, pero surge un problema: si
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.2
el segmento al que estamos accediendo es el FFFFh, cualquier valor del desplazamiento mayor que 15d
¡nos saca fuera del espacio de 1Mb! En el 8086 lo que pasa simplemente es que el sumador usado para
calcular la dirección efectiva no tiene acarreo al bit 20, por lo que FFFF0h + 000Fh=00000h que
corresponde al primer byte de la memoria física. En el 80386 veremos que esto no tiene por qué ser así.
El 80286 varía toda la filosofía de direccionamiento respecto de su predecesor. Esta CPU
incorpora otro modo de funcionamiento que permite sacar partido de los 16 Mb de espacio de
direccionamiento. Con 24 bits en el bus de direcciones en este nuevo modo protegido, el valor del
segmento cobra otro significado.
La gestión de memoria del 80286 en modo protegido es basicamente la siguiente. Existe una tabla
alojada en memoria principal y en una zona protegida denominada tabla de descriptores globales (GDT).
Cada elemento de esta tabla referencia a un bloque de memoria y sus atributos. Estos son: dirección base
del bloque en 24 bits, longitud del bloque hasta 64Kb, permisos de lectura/escritua/ejecución y otros
datos.
Si un programa hace un acceso a una dirección de memoria con valor de segmento 8 por ejemplo,
la dirección efectiva que se obtiene no es el resultado de desplazar 4 bits a la izquierda este valor, sino
que se emplea como offset respecto a la dirección base de la GDT de la que se saca la entrada
correspondiente que es la 1 (Cada entrada tiene 8 bytes de longitud) con la dirección base del segmento.
La dirección efectiva se calcula entonces sumando igual que antes el desplazamiento a este valor base.
Gracias a los datos de que se dispone en la GDT se pueden hacer comprobaciones sobre si se está
sobrepasando el límite de segmento, en cuyo caso el acceso no es permitido y se genera una excepción
del procesador. También se genera una excepción si el tipo de acceso es incompatible con los bits de
permiso almacenados en la entrada correspondiente de la GDT.
Como quiera que cada vez que se hace un acceso hay que leer los contenidos de la GDT es
conveniente guardar la entrada que se está usando en algún otro tipo de memoria que sea del mismo orden
de rapidez que los registros internos del procesador, para evitar estados de espera intolerables. Estos
almacenamientos reciben el nombre de descriptores caché. Existe uno por cada registro de segmento y
cada uno de ellos contiene el valor de la entrada de la GDT a la que apunta ese segmento. Son estos
descriptores los que se usan con todas las operaciones que implican gestión de memoria y sólo se accede
realmente a la GDT cuando el programador cambia el valor del registro de segmento relacionado. Por lo
general, estos descriptores son invisibles para el programador.
Para el 80386 esto funciona de manera análoga. Los cambios más importantes en la estructura de
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.3
un descriptor 386 son que la dirección base es ahora de 32 bits, el campo tamaño (o límite) es de 20 bits
y que se añade un campo más de 1 bit, llamado G, que indica la granularidad del segmento. Este campo
da la “unidad de medida” del segmento de la siguiente manera: si el valor del campo longitud de bloque
de un segmento es 5 y el bit G=0, entonces el tamaño del bloque son 5 * 1 byte = 5 bytes, si para este
mismo segmento el campo G=1, entonces la longitud real es 5 * 4096 bytes = 20480 bytes. De esta
manera con un campo de longitud de 20 bits se puede cubrir una longitud de segmento de hasta 4 Gb,
símplemente dándole el valor FFFFFh al límite.
La descripción de este mecanismo funciona muy bien en el modo protegido, pero también
funciona en modo real, con algunas variantes.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.4
5.2.- El modo REALMEM de 32 bits.
En el modo real del 386, que es donde nos moveremos durante casi toda la ejecución de la
simulación, los descriptores caché siguen funcionando exactamente de la misma manera que en el modo
protegido. Al resetear el micro, éste conmuta al modo real, inicializando los descriptores caché con los
valores BASE=0, LIMITE=FFFFh, G=0, y todos los permisos activados. Esta configuración coincide con
la que impone el hard de un 8086, y es la que se necesita para mantener la compatibilidad. La dirección
efectiva de un dato se calcula como dirección base del descriptor+desplazamiento, siendo el total un
número de 32 bits.
Cuando en modo real se cambia el contenido de un registro de segmento, la CPU recalcula
internamente el campo base del descriptor caché correspondiente usando la fórmula del 8086, y lo vuelve
a almacenar. No se hace ningún acceso a ninguna GDT porque simplemente no existe. El campo limite
sin embargo, no se reescribe con el valor FFFFh ni tampoco lo hace el bit G.
Esto significa que si el campo BASE de un descriptor se reescribe con el valor 0, el campo
LIMITE con el valor FFFFFh y su bit G se pone a 1, ese segmento cubrirá todo el espacio de
direccionamiento del 386. Esto significa que, desde el modo real, y usando registros de 32 bits para el
desplazamiento, estaríamos accediendo a toda la memoria sin el límite de 64Kb impuesto hasta ahora.
De hecho, esto se puede hacer, y se puede optar por dos vías: conmutar momentaneamente al
modo protegido y hacer los cambios desde allí usando una GDT con los valores deseados en los campos
LIMITE y G, o bien modificar directamente los descriptores caché usando la instrucción LOADALL. Para
obtener detalles sobre esta instrucción consultar la bibliografía.
Con mucho, la manera más segura (y más documentada) es pasar al modo protegido, crear una
GDT con una entrada que contenga el descriptor con los valores mencionados y cargar todos los registros
de segmento con la entrada de ese descriptor, con lo que su contenido pasa a los descriptores caché
correspondientes. Una vez hecho esto podemos volver al modo real, pero con los cambios en el campo
LIMITE que se necesitan.
El listado que se ofrece a continuación hace esto mismo. Los registros de segmento afectados por
el cambio en el campo límite son todos, excepto CS y SS.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.5
.model large
.data
PunteroGDT
GDT
db
db
db
db
16
47 dup(0)
0,0,0,0,0,0,0,0
0ffh,0ffh,0,0,0,92h,0cfh,0ffh
;Entrada 0. Nula
;Entrada 1. BASE=0, LIMITE=4Gb
.code realmem_text
public IniciarREALMEM
IniciarREALMEM
proc C
movzx eax,ds
shl eax,4
mov bx,offset GDT
movzx ebx,bx
add eax,ebx
mov dword ptr PunteroGDT+2,eax
lgdt pword ptr PunteroGDT
mov bx,08h
push ds
cli
;EAX=dirección física en 32 bits de la GDT
;Cargamos la GDT
;BX=entrada 1 de la GDT
;Sin interrupciones mientras estemos en el modo
protegido
mov eax,cr0
or eax,1
mov cr0,eax
jmp ModoProtegido
ModoProtegido:
ModoReal:
IniciarREALMEM
mov
mov
mov
mov
and
mov
jmp
gs,bx
fs,bx
es,bx
ds,bx
al,0feh
cr0,eax
ModoReal
sti
pop ds
ret
endp
;Cambio al modo protegido
;Fuerza un salto para borrar el pipeline
;de instrucciones en modo real
;Cargamos los registros de segmentos (y sus
;descriptores caché) con la entrada 1 de la GDT
;Salimos del modo protegido al real
;Se borra el pipeline de instrucciones
;en modo protegido
;Ya se pueden restablecer las interrupciones
end
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.6
5.3.- El gestor de memoria extendida XMS.
Entrar en el modo REALMEM no es lo único que hace falta para poder manejar la memoria entera
de la CPU a nuestro gusto. Es necesario que esté presente un gestor de bloques de memoria que impida
conflictos de utilización de un mismo bloque por varios procesos. Las funciones reservar bloque y liberar
bloque de MS DOS no sirven para este propósito, ya que sólo funcionan con memoria convencional.
[RAY88]
La especificación XMS (eXtended Memory Specification) define cómo debe ser la gestión de la
memoria extendida (la que está por encima del límite de 1Mb). Esta especificación se ha usado como
estándar en los PC AT, y hoy en día practicamente todos los programas que requieren memoria extendida
hacen uso de los servicios proporcionados por el gestor XMS, que se incluye en las últimas versiones del
DOS en forma de dispositivo: HiMem.Sys.
XMS define dos tipos de memoria, que son los que puede gestionar: un único bloque de 65520
bytes alojado a partir de la dirección física 100000h denominado memoria alta o high memory; y un
bloque de memoria extendida situada a partir de la posición 10FFF0h y que cubre el resto de la memoria
física instalada en el ordenador. Este bloque se usa como “heap” o montón, para servir de bloques de
memoria extendida (EMB) a los programas que los soliciten.
Para pedir memoria extendida, un programa hace uso de los servicios XMS y reserva un bloque
de x Kb de memoria. El gestor le devuelve un handler que el programa podrá usar a partir de ese
momento para manipular la memoria que le ha sido asignada.
Como la especificación XMS no tiene implementado el uso de REALMEM para el usuario, no
hay forma de escribir o leer bloques de memoria extendida. Para ello XMS provee de una función general
de copia ente bloques de memoria extendida, un bloque de memoria extendida y otro de memoria
convencional o bien entre dos bloques de memoria convencional. Así, para leer información desde un
EMB se copia el mismo (o la porción que interese) a un buffer en memoria convencional. Para escribir
datos en un EMB se copian éstos a memoria convencional y con una llamada al gestor se escriben en el
EMB.
Este mecanismo es extremadamente lento para nuestros propósitos aunque los suficientemente
robusto para evitar conflictos entre procesos. Todas las operaciones han de pasar por el gestor, de manera
que es muy difícil que un programa cause un error a otro por manipular un bloque que no le corresponde.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.7
Además, al no usarse nunca direcciones absolutas de memoria extendidas, sino que los bloques
se referencian por su descriptor o handler, el gestor puede mover bloques de un sitio a otro para juntar
los huecos libres y evitar una excesiva fragmentación interna del montón. Esta característica sin embargo,
deberá ser deshabilitada para nuestra aplicación, como se verá después.
El otro tipo de memoria mencionado, el bloque de memoria alta, tecnicamente forma parte de la
memoria extendida, pero tiene unas características especiales, que son independientes de que esté o no
activado el modo REALMEM.
Se ha definido como el bloque cuya dirección base es 100000h, es decir, un byte más respecto a
la última dirección física admitida (en principio) por el sistema segmento:desplazamiento en modo real
sin REALMEM. Esta dirección física límite puede ser escrita de varios modos. Sea por ejemplo igual a
FFFF:000F. Haciendo los consabidos cálculos comprobamos que la dirección efectiva es, como
suponíamos, FFFFFh.
Pero el valor del desplazamiento puede variar entre 0000 y FFFF, y en el segmento FFFF sólo
hemos usado hasta el desplazamiento 000F. Si añadimos una unidad más, la dirección queda FFFF:0010,
que en un 8086 sabemos que significa lo mismo que la dirección 0000:0000.
Y esto es a causa de que en el 8086 el sumador que forma parte de la lógica de direccionamiento
tiene sólo 20 bits, pero en el 386 éste tiene una anchura de 32 bits. Esto significa que la dirección
FFFF:0010 no hace volver a 0 la dirección de memoria, ya que esta vez el acarreo del bit 19 al bit 20 no
se pierde, sino que aparece como un bit 1 en la linea 20 del bus de direcciones, accediendo por tanto a
la posición física 100000h. La última dirección física direccionable desde el modo real puro asciende por
tanto hasta la posición 10FFEF correspondiente al par FFFF:FFFF.
Este es en definitiva el bloque conocido como high memory. Al estar en un único segmento, no
es posible guardar en él más de un programa, por lo que se usa comunmente para almacenar el kernel del
MS DOS (comando DOS=HIGH del config.sys).
Sin embargo, muchos programas que se escribieron en los tiempos del 8086 aún siguen
conservando téncicas extrañas de direccionamiento, y siguen usando el segmento FFFF para acceder a
posiciones de la tabla de interrupción ubicada al principio de la memoria, o para acceder a la zona de
variables del BIOS. Estos programas siguen confiando en que la posición FFFF:0010 es la misma que
0000:0000.
La solución adoptada consiste en un artificio hard llamada habilitación de la linea A20. El
esquema de la figura es una posible implementación de este sistema.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.8
Figura 5.3.1. Esquema del circuito de habilitación de la linea A20
Consta de un multiplexor que puede ofrecer dos salidas en función de una entrada de control. Si
dicha entrada vale 0, el contenido del bus de direcciones desde el bit 20 hasta el 31 es 0, con lo que
siempre se direcciona el primer Mb. Si vale 1, la parte alta del bus de direcciones el sistema es la misma
que la de la CPU con lo que se tiene acceso a toda la memoria disponible. El núcleo del MS DOS se
encarga de habilitar y deshabilitar esta línea cuando lanza programas para su ejecución. De esta manera,
el programa sólo ve 1Mb. Cuando se hace una llamada a MS DOS éste habilita la linea A20 y salta al
núcleo en memoria alta para atender la petición. A la vuelta, se vuelve a deshabilitar la linea A20 (en
realidad no se deshabilita, sino que se deja como estaba en el momento de llamar a MS DOS, ya que a
una aplicación le puede interesar, sobre todo si usa XMS, el dejar habilitada esta linea).
La linea de control del multiplexor está conectada a uno de los bits del bus interno del circuito
8042. Este microcontrolador se usa en el PC AT en lugar del 8255, asumiendo además funciones
adicionales, como la de provolcar un reset al micro, y esta misma. Sin embargo, esta implementación no
es estándar, y hay determinados equipos (p. ej, los PS/2), que no habilitan la linea A20 de la misma
forma. Para ofrecer un interfaz común, el gestor XMS dispone de funciones para habilitar y deshabilitar
esta linea.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.9
A continuación se ofrece el fuente del gestor de memoria implementado en la biblioteca de
programas que acompañan este trabajo. El gestor es muy simple ya que no pretender ser de uso general,
sino sólo para esta aplicación. Casi todo el trabajo se deja a la XMS. Las llamadas a este gestor son las
equivalentes a malloc() y free() del lenguaje C.
El gestor usa el modo REALMEM para acceder a la memoria extendida. Se reserva una cantidad
suficiente de ésta para el uso de la aplicación y se bloquea. Esta operación hace que el XMS no mueva
este bloque, que quedará fijo a partir de una posición física de memoria. La operación de bloqueo nos
devuielve precisamente esa dirección. El resto del trabajo consiste en asignar porciones de este bloque
al proceso según los vaya pidiendo, guardando en un vector los datos relativos al comienzo de la porción
y longitud de ésta. El gestor ofrece un método simple para fundir huecos de memoria adyacentes. Al
usuario se le devuelve un handler para referenciar uno de estos MCB (memory Control Block), a partir
del cual puede averiguar la dirección base del mismo. Este dato será el que se use en la emulación para
agilizar los accesos a memoria, que gracias a REALMEM se harán de manera directa, sin pasar por el
gestor XMS.
El gestor en sí consta de tres módulos: un fichero de cabecera que habrá que incluir en los
programas que quieran acceder a sus servicios, un módulo en lenguaje C con el gestor en sí, y dos
módulos en ensamblador: uno con el código de interfaz entre el gestor y el driver XMS, y otro con el
código de inicialización del modo REALMEM.
XMEM.H
/*
Librería para el gestor de memoria extendida de 32 bits
------------------------------------------------------Esta librería provee las siguientes funciones:
X_inicia_gestor()
X_fin_gestor()
X_malloc()
X_free()
X_coreleft()
X_leer()
X_escribir()
X_direccion()
X_tamano()
Actualiza si es necesario el valor de xmserror
(C) 1994 Miguel Angel Rodríguez Jódar.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.10
*/
int
void
int
void
unsigned long
void
void
unsigned long
unsigned long
X_inicia_gestor
X_fin_gestor
X_malloc
X_free
X_coreleft
X_leer
X_escribir
X_direccion
X_tamano
(unsigned int);
(void);
(unsigned long);
(int);
(void);
(int, unsigned long, char *, unsigned long);
(char *, int, unsigned long, unsigned long);
(int);
(int);
XMEM.C
/*
Librería para el gestor de memoria extendida de 32 bits
------------------------------------------------------Esta librería provee las siguientes funciones:
X_inicia_gestor()
X_fin_gestor()
X_malloc()
X_free()
X_coreleft()
X_leer()
X_escribir()
X_direccion()
X_tamano()
Actualiza si es necesario el valor de xmserror
(C) 1994 Miguel Angel Rodríguez Jódar.
*/
#include <stdlib.h>
#include "xms.h"
void initcpu32 (void);
int modo_virtual (void);
static
static
static
static
unsigned long mem_total, mem_libre;
HXMS hmem;
unsigned long inicio_mem, direcc_dispo;
inhA20=0;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.11
enum { LIBRE, OCUPADO, BORRADO };
#define MAX_MCB 200
typedef struct {
char estado;
unsigned long direccion;
unsigned long tamano;
} MCB;
static MCB *tab_alloc;
static int ind_alloc;
#define estado(i) tab_alloc[i].estado
#define direccion(i) tab_alloc[i].direccion
#define tamano(i) tab_alloc[i].tamano
int X_inicia_gestor (unsigned kbtotales)
{
int i;
/* si la máquina está en modo virtual, salir */
if (modo_virtual())
return 0;
/* si no hay gestor XMS, salir */
if (!xms_iniciar())
return 0;
/* construir la tabla de MCB */
tab_alloc= (MCB *) malloc(MAX_MCB*sizeof(MCB));
if (!tab_alloc)
return 0;
/* calcular la cantidad de memoria a asignar por el gestor */
if (kbtotales==0)
mem_total=mem_libre=xms_disponible()*1024L;
else
mem_total=mem_libre=kbtotales*1024L;
/* entrar al modo REALMEM 32 bits si no estamos ya en él */
if ((unsigned long)getvect(0xAA)!=0x12345678)
initcpu32();
setvect(0xAA,0x12345678);
/* asignar la memoria requerida */
hmem=xms_asignar(mem_total/1024);
if (xmserror)
return 0;
/* bloquear la memoria asignada para obtener su dirección física */
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.12
inicio_mem=direcc_dispo=xms_bloquear(hmem);
if (xmserror)
return 0;
/* si la linea A20 no está habilitada, habilítala */
if (!xms_estadoA20())
{
inhA20=1;
xms_habilA20();
}
/* iniciar la tabla de MCB asignados */
for (i=0;i<MAX_MCB;i++)
{
estado(i)=LIBRE;
direccion(i)=0L;
tamano(i)=0L;
}
/* primera entrada libre en la tabla de MCB */
ind_alloc=0;
return 1;
}
int X_malloc (unsigned long tamano)
{
int i;
/* forzamos a que sea un número par por exceso */
tamano=(tamano+1)&0xfffffffe;
/* obtener primera entrada disponible en la tabla de MCB */
for (i=0;i<ind_alloc;i++)
if (estado(i)==LIBRE || (estado(i)==BORRADO && tamano(i)>=tamano))
break;
/* si no hay entradas libres, salir */
if (i==MAX_MCB)
return -1;
/* asignar la memoria */
switch (estado(i))
{
case LIBRE:
if (mem_libre<tamano)
return -1;
estado(i)=OCUPADO;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.13
direccion(i)=direcc_dispo;
tamano(i)=tamano;
mem_libre-=tamano;
direcc_dispo+=tamano;
ind_alloc++;
return i;
case BORRADO:
estado(i)=OCUPADO;
return i;
default:
return -1;
}
}
void X_fin_gestor (void)
{
free (tab_alloc);
xms_desbloquear(hmem);
xms_liberar(hmem);
if (inhA20)
xms_deshabilA20();
}
void X_free (int mcb)
{
int i,flag;
/* si el MCB dado es inválido, salir */
if (mcb>=ind_alloc)
return;
if (estado(mcb)!=OCUPADO)
return;
/* si es el último MCB asignado, marcarlo como libre */
if (mcb==ind_alloc-1)
{
estado(mcb)=LIBRE;
direcc_dispo-=tamano(mcb);
mem_libre+=tamano(mcb);
direccion(mcb)=0L;
tamano(mcb)=0L;
ind_alloc--;
}
else
/* si no, marcarlo como borrado */
estado(i)=BORRADO;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.14
/* convertir las MCB borrados al final de la tabla en MCB libres */
for (i=MAX_MCB,flag=0;i>=0;i--)
{
if (estado(i)==BORRADO && flag==0)
flag=1;
if (estado(i)==BORRADO && flag==1)
{
estado(i)=LIBRE;
direcc_dispo-=tamano(i);
mem_libre+=tamano(i);
direccion(i)=0L;
tamano(i)=0L;
ind_alloc--;
}
if (estado(i)==OCUPADO)
break;
}
}
unsigned long X_direccion (int mcb)
{
return direccion(mcb);
}
unsigned long X_tamano (int mcb)
{
return tamano(mcb);
}
void X_escribir (char *fuente, int mcb, unsigned long offset,
numbytes)
{
/* nos aseguramos de que el número es par por defecto */
numbytes&=0xfffffffe;
offset&=0xfffffffe;
unsigned
long
/* hacemos la escritura en memoria extendida */
xms_copiar(0,fuente,hmem,(FPUNT)(direccion(mcb)-inicio_mem+offset),numbytes);
}
void X_leer (int mcb, unsigned long offset, char *destino, unsigned long numbytes)
{
/* nos aseguramos de que el número es par por defecto */
numbytes&=0xfffffffe;
offset&=0xfffffffe;
/* hacemos la lectura desde memoria extendida */
xms_copiar(hmem,(FPUNT)(direccion(mcb)-inicio_mem+offset),0,destino,numbytes);
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.15
}
unsigned long X_coreleft (void)
{
return mem_libre;
}
XMS.H
/* Fichero de cabecera para usar las funciones de manejo de XMS.
(c) 1993. Miguel Angel Rodríguez Jódar.
*/
#define HXMS
#define BOOL
#define FPUNT
unsigned int
int
void far *
typedef struct
{
char bloqueos;
char hdisp;
unsigned int tambloque;
} XMSINFO;
extern int
xmserror;
int
unsigned int
unsigned int
HXMS
BOOL
BOOL
BOOL
BOOL
BOOL
BOOL
unsigned long
BOOL
BOOL
xms_iniciar (void);
xms_version (void);
xms_disponible (void);
xms_asignar (unsigned int);
xms_liberar (HXMS);
xms_habilA20 (void);
xms_deshabilA20 (void);
xms_estadoA20 (void);
xms_copiar (HXMS, FPUNT, HXMS, FPUNT, unsigned long);
xms_reasignar (HXMS, unsigned int);
xms_bloquear (HXMS);
xms_desbloquear (HXMS);
xms_info (HXMS, XMSINFO *);
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 5.16
XMS.ASM
;***************************************************************************
;*
*
;*
Librería de funciones XMS para C.
*
;*
Implementación específica para usar con Turbo C ++ de Borland
*
;*
(c) 1993. Miguel Angel Rodríguez Jódar.
*
;*
*
;***************************************************************************
.model large
;Asumimos el modelo largo para trabajar
;con punteros largos a memoria.
.286
;Sólo 286 y superior.
llama_xms
macro popsi
local vale
mov xmserror,0
call dword ptr xmsfunc
if popsi eq 1
pop si
endif
or ax,ax
jne vale
xor dx,dx
mov al,bl
mov byte ptr xmserror,bl
ret
vale:
endm
bloque_copia
l_numbytes
h_numbytes
bhfuente
l_dfuente
h_dfuente
bhdestino
l_ddestino
h_ddestino
bloque_copia
struc
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
ends
sinfo
bloqueos
hdisp
tambloque
struc
db ?
db ?
dw ?
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
sinfo
ends
.data
xmsfunc
xmserror
movida
dd 0
;puntero al inicio del controlador XMS.
dw 0
bloque_copia <>
Pag. 5.17
public C xmserror
.code xms_codigo
public
public
public
public
public
public
public
public
public
public
public
public
public
xms_iniciar
noesta:
xms_iniciar
xms_version
xms_version
C
C
C
C
C
C
C
C
C
C
C
C
C
xms_iniciar
xms_version
xms_disponible
xms_asignar
xms_liberar
xms_habilA20
xms_deshabilA20
xms_estadoA20
xms_copiar
xms_reasignar
xms_bloquear
xms_desbloquear
xms_info
proc C
push es
mov ax,4300h
int 2fh
;comprobar presencia del gestor XMS
cmp al,80h
jne noesta
mov ax,4310h
int 2fh
;obtener dirección de llamada del gestor
mov word ptr xmsfunc,bx
mov word ptr xmsfunc+2,es
mov ax,1
pop es
ret
xor ax,ax
pop es
ret
endp
proc C
mov ah,0
llama_xms 0
ret
endp
;obtener versión en AX
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
xms_disponible
xms_disponible
xms_asignar
xms_asignar
xms_liberar
xms_liberar
xms_habilA20
xms_habilA20
xms_deshabilA20
xms_deshabilA20
xms_estadoA20
xms_estadoA20
proc C
mov ah,8
llama_xms 0
ret
endp
Pag. 5.18
;obtener XMS libre (mayor bloque EMB) en Kb
proc C mempedida:word
mov ah,9
mov dx,mempedida;dada en Kb
llama_xms 0
;Asignar bloque de EMB
mov ax,dx
;handle en AX para retorno
xor dx,dx
ret
endp
proc C handle:word
mov ah,0ah
mov dx,handle
;liberar EMB
llama_xms 0
ret
endp
proc C
mov ah,05h
llama_xms 0
ret
endp
proc C
mov ah,06h
llama_xms 0
ret
endp
proc C
mov ah,07h
llama_xms 0
ret
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
xms_copiar
numbytes:dword
Pag. 5.19
proc C hfuente:word, dfuente:dword, hdestino:word, ddestino:dword,
mov
mov
mov
mov
ax,word ptr numbytes
movida.l_numbytes,ax
ax,word ptr numbytes+2
movida.h_numbytes,ax
mov ax,hfuente
mov movida.bhfuente,ax
mov
mov
mov
mov
ax,word ptr dfuente
movida.l_dfuente,ax
ax,word ptr dfuente+2
movida.h_dfuente,ax
mov ax,hdestino
mov movida.bhdestino,ax
mov
mov
mov
mov
xms_copiar
xms_reasignar
xms_reasignar
xms_bloquear
xms_bloquear
ax,word ptr ddestino
movida.l_ddestino,ax
ax,word ptr ddestino+2
movida.h_ddestino,ax
push si
mov si,offset movida
mov ah,0bh
;Mover bloques EMB
llama_xms 1
ret
endp
proc C handle:word, longitud:word
mov dx,handle
mov bx,longitud
mov ah,0fh
llama_xms 0
ret
endp
proc C handle:word
mov dx,handle
mov ah,0ch
llama_xms 0
mov ax,bx
ret
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
xms_desbloquear
xms_desbloquear
xms_info
xms_info
Pag. 5.20
proc C handle:word
mov dx,handle
mov ah,0dh
llama_xms 0
ret
endp
proc C handle:word, pinfo:ptr sinfo
mov dx,handle
mov ah,0eh
llama_xms 0
push es
les si,pinfo
mov es:[si].bloqueos,bh
mov es:[si].hdisp,bl
mov es:[si].tambloque,dx
pop es
ret
endp
end
CODE32.ASM
.model large
.data
mem48
gdt
db 6 dup (0)
db 8 dup (0)
db 0FFh, 0FFh, 0, 0, 0, 92h, 0CFh, 0FFh
.code pmode32
public C initcpu32
public C modo_virtual
modo_virtual
.386p
proc C
smsw ax
and ax,1
ret
.286
modo_virtual
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
initcpu32
.386p
Pag. 5.21
proc C
mov mem48,16
mov eax,seg gdt
shl eax,4
mov bx,offset gdt
movzx ebx,bx
add eax,ebx
mov dword ptr mem48+2,eax
lgdt pword ptr mem48
mov bx,08h
push ds
cli
mov eax,cr0
or eax,1
mov cr0,eax
jmp ModoProtegido
ModoProtegido:
mov
mov
mov
mov
and
mov
jmp
gs,bx
fs,bx
es,bx
ds,bx
al,0FEh
cr0,eax
ModoReal
ModoReal:
sti
xor
mov
mov
pop
ret
ax,ax
fs,ax
gs,ax
ds
.286
initcpu32
endp
end
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.1
6. DESCRIPCION DEL HARDWARE DE
AUDIO A IMPLEMENTAR EN EL PC.
6.1. Esquema funcional y eléctrico.
El prototipo de la tarjeta de audio desarrollada consta de una placa madre que lleva la lógica
necesaria para generar las señales de chip select a los diferentes módulos conectados a ella. A través de
conectores tipo bus ISA se envían a estos módulos alimentación, bus de datos, señales de control y
señales analógicas.
Los módulos conectados son cuatro: un DAC para el canal izquierdo de audio, otro para el canal
derecho, un conversor ADC y un timer programable tipo 8253.
La alimentación proviene de otra placa, y suministra 3 tensiones: +5V, +12V y -12V. La tensión
de 5 voltios se usa para los circuitos digitales y para las referencias de tensión del ADC. Este último
también se alimenta con 5 voltios. La corriente suministrada es alrededor de 700mA.
Las tensiones de +/- 12V alimentan a todos los amplificadores operacionales, a los DAC’s y
eventualmente, a un amplificador de potencia exterior. La corriente suministrada en este caso es alrededor
de 3A.
La placa madre se conecta por una parte al módulo de alimentación, por otra al puerto paralelo
del PC mediante un conector Centronics de 36 pines. Dispone de una entrada analógica conectada
directamente a la tarjeta ADC, y dos salidas analógicas provenientes de los dos DAC’s. El nivel de cada
salida se puede calibrar por separado con ayuda de un potenciómetro, antes de pasar a la etapa de
potencia.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.2
Figura 6.1.1. Esquema de bloques de la tarjeta.
A continuación estudiaremos el funcionamiento de cada módulo por separado, y después veremos
cómo se realiza el interfaz con el puerto paralelo.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.3
El conversor digital-analógico.
Para describir este módulo lo dividiremos en tres secciones:
T
Latch de almacenamiento de muestras.
T
Conversor digital-analógico.
T
Filtro pasa-bajos de salida.
El esquema eléctrico corresponde al de la figura 6.1.2.
Figura 6.1.2. Esquema eléctrico de la etapa de conversión digital-analógica.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.4
La primera sección consta de un circuito integrado 74HCT573 que es un latch de 8 bits con carga
por nivel alto y salida no invertida. Este latch tiene su bus de entrada conectado al bus del sistema,
estando la entrada de habilitación de carga conectada al puerto paralelo a través de la lógica de
decodificación. Cuando se reciba un 1 en esta entrada, el bus de salida del latch seguirá las variaciones
de los bits del bus del sistema, y cuando valga 0, el bus de salida retendrá el último valor binario aplicado
en la entrada. Este circuito nos permitirá retener un valor para aplicarlo al circuito DAC mientras el bus
está ocupado con otro dispositivo.
La salida del 74HCT573 va directamente al conversor digital-analógico (DAC). Para este proyecto
se ha usado un DAC0808 por su bajo coste, su velocidad de respuesta y su facilidad de uso. Dispone de
dos entradas por donde circula una corriente de referencia Iref, fijada mediante dos resistencias de 7,5K.
Sus entradas admiten un dato de 8 bits en binario natural, dando la salida en dos patillas Iout y Iout\. La
primera ofrece una corriente cuyo valor es Iref*DATO/256, y la segunda tiene un valor igual a
Iref*(DATO complementado)/256.
Como necesitamos el valor analógico en forma de tensión, las patillas Iout e Iout\ van a uno de
los amplificadores operacionales que posee el integrado doble operacional TL082, que se emplea aquí
como conversor corriente-tensión.
La salida de este primer operacional ya es una tensión analógica, pero todavía tiene discontinuidades que aparecen como “escalones” en el osciloscopio. Para suavizar éstos, y por tanto, eliminar
armónicos indeseados, se recurre al empleo de un filtro paso bajos de 2º orden activo formado por el
segundo operacional del TL082 y sus componentes asociados, conectado a la salida del DAC y acoplado
al mismo mediante un condensador electrolítico de 22uF. Los componentes del filtro se han calculado
para que la frecuencia de corte esté próxima a los 18KHz. La salida puede ir ya hacia el amplificador de
potencia o equipo de grabación.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.5
El conversor analógico-digital
Al igual que el módulo anterior, éste se puede dividir en tres secciones:
T
Circuito de entrada y acomodación de señal.
T
Conversor analógico-digital.
T
Buffer triestado.
El esquema eléctrico corresponde a la figura 6.1.3.
El circuito de entrada tiene una doble función. Por una parte, amplifica las señales de audio
presentes en su entrada hasta un nivel aceptable, y por otra parte, introduce un offset en la salida de tal
forma que la señal que resulta de esta etapa es unipolar y comprendida entre 0 y 5V. Está compuesto por
un operacional tipo 741 o TL081 configurado como amplificador inversor con una ganancia igual a 10.
La patilla no inversora está conectada a una tensión de 4,5V para que el operacional en ausencia de señal
entregue este valor al ADC. Dicha tensión de offset es regulable gracias a un potenciómetro multivuelta.
En el montaje se debe calibrar este potenciómetro de tal forma que cortocircuitando la entrada del
operacional a masa, y con todos los componentes del módulo en funcionamiento, éste dé una salida igual
a 128d.
El conversor analógico-digital es un ADC0820 de National Semiconductor. Este circuito tiene
unas características muy interesantes que merece la pena destacar. En principio, y aún sin tener un precio
elevado, tiene un periodo de conversión de 2us como máximo. Esto es posible ya que combina dos
ADC’s de 4 bits tipo flash en una sola pastilla. Uno de los conversores ofrece los 4 bits más
significativos, y el otro los 4 bits menos significativos. El proceso de conversión tiene dos fases:
En la primera se enfrenta la señal de entrada al primer conversor flash que ofrece directamente
una salida digital correspondiente a los 4 primeros bits. Esta salida va a un DAC que la vuelve a convertir
a analógica.
En la segunda fase la señal de entrada se resta de la señal analógica convertida, y el resultado se
ofrece al segundo convertidor flash. Su resultado es la parte menos significativa del dato completo de 8
bits.
El conversor puede funcionar en dos modos, según el valor de la patilla MODE. Si MODE vale
0, el conversor trabaja en modo WR, y si vale 1 trabaja en modo RD-WR o en el modo Stand-alone
operation. Este último será el que se use, por permitir que el conversor funcione independientemente del
resto del sistema. El cronograma de las señales del ADC en este modo es el de la figura 6.1.4.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.6
Figura 6.1.3. Circuito del módulo de conversión analógico-digital.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.7
Figura 6.1.4. Cronograma del funcionamiento combinado ADC0820-8253
Las entradas CS\ y RD\ están permanentemente a nivel bajo. En esta situación una conversión
empieza con el flanco de subida de WR\. Aproximadamente 1us después, la salida INT pasa a nivel alto
indicando el fin de la conversión. Esta salida INT va por una parte a la placa principal para ser enviada
como señal de interrupción. Por otra parte va a la entrada GATE1 del temporizador 8253. El pulso de INT
provoca que el 8253 inicie una cuenta que se habrá programado con anterioridad. Al finalizar dicha
cuenta se generará un pulso de nivel bajo en la salida OUT1 del timer, que está conectada a la entrada
WR\ del ADC. De esta forma se provocan conversiones de manera automática y a una frecuencia de
muestreo elegida por el usuario.
Como la entrada CS\ va a estar siempre activada, la salida digital está siempre disponible en el
bus de salida del conversor, pero ello podría acarrear conflictos si es el ordenador quien va a escribir en
él. Por ello es necesario el uso de un buffer provisto de habilitación tri-estate. El integrado elegido es el
74HCT541 que dispone de un bus de entrada, otro de salida no invertida. Dos señales G1\ y G2\ habilitan
éste último al forzarlas a nivel bajo, lo que nos posibilitará desconectar desde el ordenador el ADC del
bus sin perjuicio de que cesen las conversiones. Además protege al ADC de una sobrecarga en sus buses.
Esto puede pasar ya que el método que se va a usar para escribir un dato en el puerto paralelo consistirá
en poner todas las lineas de datos del bus a 1 lógico, y después hacer que el dispositivo que escribe fuerce
las lineas que desee a 0 para escribir el dato. Se necesita por tanto un integrado que tenga la “fuerza”
suficiente como para vencer a la tensión existente en el bus.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.8
Temporizador programable.
Consta de un circuito integrado 8253 de Intel igual al de los primeros PC, más un oscilador que
genera una señal cuadrada de 1,17924375MHz. Este oscilador consta de un cristal oscilador de
18,8679MHz y un circuito contador de 4 bits 74161 del que sólo se emplea la última salida, en donde
encontramos una señal de reloj de frecuencia igual a 1/16 de la frecuencia de reloj de entrada.
El circuito de este módulo es el 6.1.5. Como se puede ver el timer tiene casi todas sus lineas de
control conectadas a la regleta de conexiones. Realmente es la placa madre la que provee de señales de
control a este módulo. De sus tres contadores, el 0 se usa como generador de onda cuadrada para generar
una interrupción periódica que será la que provoque el disparo del emulador DMA. El contador 1 se
emplea para provocar que el ADC0820 este continuamente realizando conversiones y se programa en el
modo ‘hardware triggered strobe’. El contador 2 no se usa.
Como señal de habilitación por parte de la placa madre se usa la propia entrada CS\ del 8253. La
entrada RD\ está siempre a 1 ya que no se van a hacer lecturas de este dispositivo. Las entradas A1 y A0
seleccionan uno de los cuatro registros internos del timer. Todas las entradas de control estarán bajo el
control del ordenador, quien será el responsable de activarlas de acuerdo con la secuencia de escritura que
indica el fabricante.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.9
Figura 6.1.5. Circuito del temporizador generador de interrupciones.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.10
Placa principal del sistema.
Es quien actúa de interfaz entre los módulos y el puerto paralelo. Se encarga de gestionar las
lineas de control desde el puerto parlelo hacia los módulos, y de estos a las lineas de estado hacia el
ordenador.
El puerto paralelo tiene 4 lineas de control: C0, C1, C2 y C3 pero entre todos los dispositivos, las
entradas de control son 7: 4 para cada chip select más 3 para las lineas A1, A0 y WR\ del 8253. Como
sólo podemos usar un puerto paralelo, y no es conveniente usar las lineas del propio bus de datos como
lineas de control (ello obligaría a usar más escrituras en el puerto para realizar una operación) debemos
hallar una forma de compartir estas señales de control.
La solución más simple y que implica menos intervención software consiste en lo siguiente: en
primer lugar se asignan estas 4 señales a los chip select de los 4 módulos. Así, C0 irá al DAC izquierdo,
C1 al derecho, C2 al ADC y C3 al timer. De los cuatro módulos, tres de ellos (los dos DAC’s y el ADC)
deben poder estar activos a un tiempo mientras que el timer sólo debe estar activo mientras se realiza la
escritura de un contador. Además la operación de escritura del 8253 es incompatible con la emisión de
muestras a alguno de los DAC’s o la recogida de muestras desde el ADC, por lo que estos tres módulos
deben quedar completamente desconectados del bus. Esto se consigue usando la señal C3 del timer como
“cerrojo” para el resto las otras 3 señales de control. Así, si el C3 vale 1, éste quedará inactivo y las otras
tres señales estarán conectadas a las entradas de habilitación de los módulos. En cambio, si vale 0, la
señal C0 pasará a ser WR del 8253, C1 pasa a ser A1\ y C2 se conecta a A0.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
Pag. 6.11
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Registro de control del puerto paralelo.
no usada
7
no usada
no usada
6
5
EN_INT
4
C3
C2
3
2
C1
C0
1
0
ENT_INT tiene el mismo significado que EN_ACK. Si vale 1 se permiten interrupciones
provenientes de este puerto, y si está a 0 se deshabilitan.
Señal
C3=0 (no timer)
C1=1 (con timer)
C2
0=Deshabilitar salida del ADC
1=Habilitar salida del ADC
0=Selecciona A0=0
1=Selecciona A0=1
C1
0=Habilitar DAC derecho
1=Deshabilitar DAC derecho
0=Selecciona A1=1
1=Selecciona A1=0
C0
0=Habilitar DAC izquierdo
1=Deshabilitar DAC izquierdo
0=Impide escritura en el 8253
1=Permite escritura en el 8253
La única señal de entrada al puerto paralelo que se usa es ACK\ que dispara la interrupción del
puerto paralelo cuando alguna de las dos lineas de interrupción posibles (OUT0 o INT) pasan de 0 a 1.
El circuito eléctrico de la placa principal es el de la figura 6.1.6.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.12
Figura 6.1.6. Circuito de la placa madre.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.13
Módulo de alimentación.
Está construido alrededor de los integrados reguladores 7805, 7812 y 7912. Estas tres tensiones
se recogen de dos transformadores, siendo rectificadas por sendos puentes de diodos. Cada salida de
tensión está filtrada por un condensador de alta capacidad (2200uF). Un condensador de 100nF de
poliéster se encarga de derivar a tierra cualquier señal que se pudiera filtrar desde los circuitos digitales
a causa de las transiciones bruscas de nivel que provocan. El circuito por lo demás es el estándar para
estos casos, siendo innecesario cualquier otro comentario. La figura 6.1.7 muestra su esquema.
Figura 6.1.7. Esquema eléctrico del módulo de alimentación.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.14
6.2.- Programación de la tarjeta de sonido.
En la sección anterior se ha mostrado una tabla con los bits de control que controlan el
funcionamiento de la tarjeta. En ésta se darán algunos ejemplos de funcionamiento.
Para ello, supondremos que el puerto de datos tiene la etiqueta lptdata, el puerto de estado lptstd
y el puerto de control lptctrl.
La tarjeta permite realizar, entre otras, las siguientes operaciones:
L
Utilización de cualquiera de los dos DAC’s o los dos a un tiempo para reproducir sonido
monoaural.
L
Utilización de los dos DAC’s en modo estéreo.
L
Modo escucha: muestreo desde el ADC y reproducción simultánea en cualquiera de los
DAC’s sin intervención de la CPU.
L
Modo multiplexado: muestreo desde el ADC y reproducción en mono o estéreo de otra
muestra independiente de la convertida por el ADC.
L
Cambio de la frecuencia de muestreo tanto de reproducción como de conversión ADC.
Utilización de cualquiera de los dos DAC’s o los dos a un tiempo para reproducir sonido
monoaural.
Para ello sólo hay que activar cuál o cuáles queremos usar. Para ello basta hacer un OUT al puerto
lptctrl con los bits del DAC correspondiente a 0. Después basta con enviar datos al puerto lptdata sin tener
que usar ningún protocolo.
Utilización de los dos DAC’s en modo estéreo.
Se activará alternativamente el DAC izquierdo y el derecho. En cada activación se escribirá el
dato deseado a lptdata para que cada DAC lo recoja. Un procedimiento para hacer esto sería:
Procedimiento Estereo (dato_izq, dato_der)
out lptctrl,00000011b
;desactivamos los DAC’s.
out lptdata,dato_izq
;ponemos dato_izq en el bus del sistema.
out lptctrl,00000010b
;activamos el DAC izquierdo para que lea
;la muestra en su latch.
out lptctrl,00000011b
;desactivamos DAC izquierdo. El dato
;sigue en su latch.
out lptdata,dato_der
;ponemos dato_der en el bus del sistema.
out lptctrl,00000001b
;activamos DAC derecho.
out lptctrl,00000011b
;desactivamos DAC derecho.
Fin
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.15
Modo escucha: muestreo desde el ADC y reproducción simultánea en cualquiera de los DAC’s sin
intervención de la CPU.
Esta operación se inicia activando el bit C2 para permitir que el ADC vuelque sus datos al bus,
y poniendo a 0 los bits C1 y/o C0 para escuchar lo que está siendo digitalizado en ese momento. El dato
también está presente en el puerto paralelo desde donde el ordenador lo puede leer usando como
protocolo la señal ACK (condición ACK=1) o la interrupción correspondiente.
Es necesario haber inicializado el contador 1 con un valor válido para la frecuencia de muestreo
del ADC para que aquél envíe solicitudes de conversión a éste.
Modo multiplexado: muestreo desde el ADC y reproducción en mono o estéreo de otra muestra
independiente de la convertida por el ADC.
Este es el modo más flexible que tiene la tarjeta. De esta manera se usa el bus como si hubiera dos
distintos: uno de entrada desde el ADC a la CPU y otro de salida desde la CPU a los DAC’s. Para ello
hay que dedicar un tiempo de bus a cada dispositivo, siendo el ordenador el encargado de gestionarlo.
Este mecanismo permite realizar efectos en tiempo real tales como eco, reverb, distorsión u otros
más complejos y espectaculares.
El siguiente procedimiento muestra cómo usar este modo:
Procedimiento Lee_y_escribe (dato_izq, dato_der, var dato_entrada)
Estereo (dato_izq, dato_der)
out lptdata,11111111b
;Pone el bus a nivel alto para poder escribir en él
out lptctrl,00010111b
;Habilita ADC e interrupción del timer
dato_entrada= in (lptdata) ;Lee la muestra y la pone en la variable de salida
Fin
Esta función debe ser llamada desde dentro de la interrupción del ADC. Si no se quieren usar
interrupciones se debe chequear el estado del bit 6 de lptstd. El paso del valor de este bit de 0 a 1 indica
que hay datos disponibles. El chequeo debe producirse justo antes de la lectura del ADC.
Cambio de la frecuencia de muestreo tanto de reproducción como de conversión ADC.
Para ello habremos de programar al 8253 de la tarjeta según se ha indicado (modo 3 para la
interrupción periódica de los DAC’s y modo 5 para la del ADC). El esquema de programación de un
circuito 8253 se vio en el capítulo 4. Aquí la cosa no es tan sencilla. Lo que en el timer del sistema es un
simple OUT, aquí se convierte en un procedimiento entero, que escribiremos en lenguaje C para este
ejemplo. Los pasos que se ejecutan son:
T
Deshabilitar todos los dispositivos.
T
Poner en el bus del sistema el valor que se va a escribir en el 8253.
T
Activar C3. Programar C2 y C1 dependiendo del registro interno al que se vaya a acceder. Poner
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 6.16
C0=1 para permitir la escritura.
T
Esperar un tiempo para que los registros internos del 8253 tengan tiempo de recoger el dato.
T
Desactivar C3 con lo que el timer queda desconectado del bus.
El procedimiento es el siguiente:
void e8253 (int a1, int a0, int valor)
{
int mascara;
mascara=(a0<<2)|((!a1)<<1)|0x19;
outp(lptdata,valor);
outp(lptctrl,mascara);
esperar();
/* se realiza una espera de unos cuantos microsegundos */
outp(lptctrl,mascara&0xfe);
}
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.1
7. LA RUTINA DE EJECUCION DEL
INTERPRETE MOD
7.1.- Descripción del funcionamiento del intérprete MOD.
El intérprete MOD que presentaremos en este capítulo está basado en las ideas que se han
expuesto en los capítulos precedentes. Las características de este intérprete son:
T
T
T
T
T
T
T
T
T
Soporta 4 canales de sonido digital en 8 bits completamente independientes.
Puede reproducir sonido a través del altavoz interno, un DAC en el puerto paralelo, una Sound
Blaster o bien a través de la tarjeta de proyecto descrita.
Soporta tanto mezcla monoaural como mezcla estereofónica (la nativa del Amiga).
Optimizado para frecuencias de muestreo de hasta 32KHz.
Cada instrumento puede ocupar tanto espacio como memoria haya en el sistema rompiendo la
barrera de 64K por instrumento.
Los instrumentos se almacenan en memoria extendida XMS dejando la mayor parte de la
memoria convencional libre.
Se soportan casi todos los comandos de la versión 2.0 de la especificación .MOD
Se usa el modelo de memoria 32-bit flat pointer para asegurar la compatibilidad con DOS y
permitir la compilación con un compilador estándar de 16 bit para DOS (Turbo C++ 1.0).
Ampliable hasta 16 canales sin disminución de la frecuencia de muestreo.
Durante su funcionamiento se usan las siguientes estructuras de datos:
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.2
Tabla de instrumentos.
Es una matriz de 31 entradas. Cada entrada es un registro con el siguiente contenido:
st_ins
nombre_ins
long_ins
volum_ins
loop_s
loop_l
base_ins
mcb
st_ins
struc
db 22 dup(?)
dw ?
dw ?
dw ?
dw ?
dd ?
dw ?
ends
Cada entrada de esta matriz se rellena con los datos proporcionados por el fichero .MOD. El
campo base_ins se rellena en el momento de pedir memoria para el instrumento, y contiene la dirección
física (no el descriptor) de la primera muestra del instrumento. El descriptor se almacena en el campo
mcb (Memory Control Block) para poder acceder al instrumento desde el módulo cargador.
Los campos loop_s y loop_l contienen respectivamente el desplazamiento en bytes desde el
principio del instrumento de la primera muestra que interviene en el loop, y la longitud en bytes del
mismo. La porción de instrumento definida por estos campos se leerá una y otra vez después de haberse
leído todas las muestras del instrumento una vez. Esto sirve para definir sonidos ininterrumpidos. Si el
instrumento no tiene loop, estos campos valdrán respectivamente 0 y 1.
El volúmen del instrumento, volum_ins, es el volúmen al que se leerá el instrumento, si no hay
ningún comando que altere este valor. El rango es el usual en los MOD: de 0 a 64.
La longitud del instrumento se almacena en un entero de 2 bytes, long_ins, por lo cual, y en
principio solo se permiten instrumentos de hasta 64K. La rutina intérprete convierte este valor en 32 bits
de modo que alterando el módulo de carga se pueden leer instrumentos de más de 64K.
El campo nom_ins contiene el nombre del instrumento. Originalmente este campo guardaba la
trayectoria completa del fichero donde estaba almacenado, ya que el original Sound Tracker mantenía en
discos separados cada uno de los grupos de instrumentos de que constaba su librería de sonidos. Cuando
se cargaba una canción dentro de este programa, este campo indicaba dónde había que buscar el fichero
que contenía el instrumento requerido. No se usa durante el funcionamiento de esta rutina.
Tabla de punteros a patrones.
Es un vector de 64 posiciones. Cada posición es un puntero largo de modo real al principio de cada uno
de los patrones que forman el módulo.Cada patrón contiene los datos de los 4 canales para un total de 64
lineas de ejecución.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.3
Registro de canal.
Existe uno por cada canal de sonido que se va a emular. Contiene todos los datos que hacen falta durante
la mezcla digital.
Es el más usado, y debe ubicarse en una dirección de memoria que sea frontera de doble palabra
a fin de optimizar los accesos a cada uno de sus campos.
Su contenido es el siguiente:
st_muest
fin_muest
pri_muest
looplm
loopsm
basetabla
volumen
vol_play
vol_tabla
pitch
valor_slide
arpegio1
arpegio2
valtslide
finslide
valor_pitch
num_ins
valefecto
flag_pitch
flag_slide
flag_arpegio
flag_tslided
flag_tslideu
st_muest
struc
dd 1
dd 0
dd 1
dd 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
dw 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
ends
Este registro se actualiza con cada llamada al bucle de mezcla (que se describirá más adelante).
Los cuatro primeros campos se rellenan con los correspondientes valores del instrumento leído en cada
canal definido en la linea actual del patrón actual del módulo. Esta función la realiza la macro act_canal.
El campo volumen contiene el valor del volúmen por defecto del instrumento, o el volúmen actual
definido por cualquiera de los comandos que alteran su valor.
El campo vol_play contiene el valor del volúmen real con el que será tocado el instrumento. Este
valor difiere del del campo volumen en que aquél está afectado por el valor del volúmen general del
canal, seleccionable por el usuario. El contenido de vol_play es, en cada instante igual a
volumen*volumen_del_canal/256.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.4
El campo vol_tabla contiene el valor de un puntero corto (referido a DS) que apunta a una tabla
de 256 posiciones. Cada valor de esta tabla es el resultado de multiplicar el valor de la muestra leída por
el valor de vol_play y dividido entre 64. El valor de este campo cambia cada vez que lo hace vol_play,
y permite multiplicar y dividir bytes con mucha mayor rapidez que con la instrucción imul (se ganan de
5 a 10 ciclos por multiplicación).
El campo pitch contiene el valor de la nota en el formato en que es usada en el Amiga.
Cuando se vio el apartado referente al 8364 se apuntó que la manera de almacenar la frecuencia de
muestreo de cada canal era a través de un divisor que dividía a la frecuencia base de funcionamiento del
chip. Este valor es el que se usa en los comandos que pueden alterarlo (slide, arpegio, toneslide, etc...).
El intérprete no puede usar este valor directamente para manejar el tono de la muestra. En el
capítulo 5 se introdujo la manera de hacer sonar distintas muestras a distintas frecuencias de muestreo
menores que un valor de frecuencia de muestreo máxima, usando un solo timer (y por tanto una sola
frecuencia de muestreo común). En el Amiga esto no hace falta dado que cada canal tiene su propio timer
y su propia lógica de DMA, pero aquí sólo tenemos un timer.
El procedimiento que se describió en su momento consiste en usar una tabla de incrementos
definida para cada nota posible. Esta tabla contiene los valores que se han de añadir al valor del campo
pri_muest para que vaya direccionando una a una las diferentes muestras que componen el instrumento
al ritmo indicado por la nota que se quiere tocar. Esto es, si la tabla contiene los valores 1,0,1,0,1,0,... el
instrumento se tocará a la mitad de la frecuencia de muestreo nominal. Si contiene los valores
1,1,0,1,1,0,1,1,0,... el instrumento se leerá a un ritmo de 2/3 de la frecuencia de muestreo nominal.
Cada vez que se recalcula el valor de pitch se usa para calcular la dirección de la correspondiente
tabla de incrementos. Esta dirección se guarda en el campo basetabla.
El número de instrumento usado se guarda en el campo instrumento.
El resto de los campos están relacionados con los distintos comandos soportados por el intérprete
y se discutirán cuando se comente la rutina de cálculo de efectos.
canal4_mono
;
;
;
;
;
;
;
;
macro
local buc_canal1,buc_canal2,buc_canal3,buc_canal4
local setloops_c1,setloops_c2,setloops_c3,setloops_c4
local fin_canal1,fin_canal2,fin_canal3,fin_canal4
Uso de los registros
ECX
= contador del bucle
EDX
= proximo valor de la tabla Bresenham
EBX
= direccion base de la tabla Bresenham
EBP
= puntero a la muestra a leer
ES:DI = puntero al buffer DMA
EAX
= muestra le¡da
ESI
= direccion de la tabla de volumenes para cada canal
;Procesando canal 1
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
buc_canal1:
Pag. 7.5
movzx ecx,bytes_trans
les di,bloque_lle
movzx edx,br_indice
mov ebp,tab_muest1.pri_muest
movzx esi,tab_muest1.vol_tabla
movzx ebx,tab_muest1.basetabla
xor eax,eax
; Longitud buffer DMA
; Direcci¢n buffer DMA
; Indice al proximo valor de la tabla de incrementos
; Direcci¢n de la pr¢xima muestra a leer
; Tabla de traducci¢n para el vol£men de este canal
; Direcci¢n base de la tabla de incrementos para esta nota
; Ponemos a 0 todo el registro EAX.
mov al,fs:[ebp]
mov al,[esi+eax]
stosb
mov al,[ebx+edx]
; AL=muestra actual
; AL=AL*volumen1/128
; Almacena muestra
; Lee el valor para incrementar el puntero a la pr¢xima
muestra
inc dl
add ebp,eax
cmp ebp,tab_muest1.fin_muest
ja setloops_c1
loop buc_canal1
jmp fin_canal1
setloops_c1: mov ebp,tab_muest1.loopsm
mov eax,tab_muest1.looplm
mov tab_muest1.fin_muest,eax
xor eax,eax
loop buc_canal1
;
;
;
;
;
;
;
fin_canal1:
; Almacenamos el puntero a la siguiente muestra
mov tab_muest1.pri_muest,ebp
Incrementa ¡ndice a la tabla de incrementos
Actualiza puntero a la siguiente muestra
"Se ha terminado de leer la muestra o el loop?
S¡, vuelve al principio del loop
Siguiente muestra
Fin de este canal
EBP=principio del loop
; fin_muestra ahora es el fin del loop
; Volvemos a borrar EAX
; Y seguimos leyendo muestras
;Procesando canal 2 (la mecánica es análoga al canal 1)
movzx ecx,bytes_trans
les di,bloque_lle
mov ebp,tab_muest2.pri_muest
movzx esi,tab_muest2.vol_tabla
movzx ebx,tab_muest2.basetabla
xor eax,eax
buc_canal2:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
add es:[di],al
inc di
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest2.fin_muest
ja setloops_c2
loop buc_canal2
jmp fin_canal2
setloops_c2: mov ebp,tab_muest2.loopsm
mov eax,tab_muest2.looplm
mov tab_muest2.fin_muest,eax
xor eax,eax
loop buc_canal2
fin_canal2:
; En lugar de almacenar la muestra se a' ade a la anterior
; Incrementamos el puntero al buffer DMA
mov tab_muest2.pri_muest,ebp
;Procesando canal 3
movzx ecx,bytes_trans
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.6
les di,bloque_lle
mov ebp,tab_muest3.pri_muest
movzx esi,tab_muest3.vol_tabla
movzx ebx,tab_muest3.basetabla
xor eax,eax
buc_canal3:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
add es:[di],al
inc di
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest3.fin_muest
ja setloops_c3
loop buc_canal3
jmp fin_canal3
setloops_c3: mov ebp,tab_muest3.loopsm
mov eax,tab_muest3.looplm
mov tab_muest3.fin_muest,eax
xor eax,eax
loop buc_canal3
fin_canal3:
mov tab_muest3.pri_muest,ebp
;Procesando canal 4
movzx ecx,bytes_trans
les di,bloque_lle
mov ebp,tab_muest4.pri_muest
movzx esi,tab_muest4.vol_tabla
movzx ebx,tab_muest4.basetabla
xor eax,eax
buc_canal4:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
add al,80h
add es:[di],al
inc di
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest4.fin_muest
ja setloops_c4
loop buc_canal4
jmp fin_canal4
setloops_c4: mov ebp,tab_muest4.loopsm
mov eax,tab_muest4.looplm
mov tab_muest4.fin_muest,eax
xor eax,eax
loop buc_canal4
fin_canal4:
mov tab_muest4.pri_muest,ebp
mov br_indice,dx
; Almacenamos índice al pr¢ximo valor de la tabla de
incrementos
endm
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.7
El emulador DMA.
Consiste en una rutina activada por un timer, que en el caso de la tarjeta de proyecto es el propio
timer de la misma, y en un DAC simple es el timer del sistema. Esta rutina simplemente carga el puntero
de dirección actual y lee el siguiente dato a enviar al puerto paralelo (o a los dos siguientes, si es estéreo)
.Las muestras se envían entonces usando el protocolo adecuado:
L
Si el dispositivo de salida es el altavoz interno, usa la tabla COMPRES.INC para obtener el
verdadero valor de la muestra que se enviará.
L
Si es un DAC simple conectado a las lineas de datos de un puerto paralelo, se envía la muestra
a éste sin más.
L
Si es la tarjeta de proyecto, se activa el canal izquierdo y se envía la muestra correspondiente. Se
desactiva éste, y se activa el derecho enviándose también su muestra. Después se desactivan los dos.
Una vez cmpletada la transferencia se decrementa el contador del emulador DMA, y si llegó a 0
se llama a la rutina prep_datos, que corresponde a las tareas a realizar cuando se da la condición de EOC
(End Of Count) en el emulador.
Finalmente, se restauran los registros, se manda un EOI al 8259 y se sale de la rutina.
Este es el fuente de la rutina de interrupciones para el caso de la tarjeta de proyecto:
intproy
proc far
push ax
push bx
push dx
push si
push ds
push es
mov al,20h
out 20h,al
mov ax,dgroup
mov ds,ax
cmp terminado,0
jne fin_iproy
les si,bloque_dma
mov bx,indice_int
mov al,es:[bx+si]
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.8
mov dx,lptdata
out dx,al
mov al,00010010b
mov dx,lptctrl
out dx,al
jmp $+2
mov al,00010011b
out dx,al
jmp $+2
mov al,es:[bx+si+1]
mov dx,lptdata
out dx,al
jmp $+2
mov al,00010001b
mov dx,lptctrl
out dx,al
jmp $+2
mov al,00010011b
out dx,al
add indice_int,2
sub cont_int,2
jz fin_bl_pry
fin_iproy:
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
fin_bl_pry:
call prep_datos
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
intproy
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.9
Rutina de cálculo de efectos.
Los efectos se procesan 50 veces por segundo. En el Amiga esta tarea la hacía una rutina disparada
por la interrupción del retrazo vertical del monitor. Esto suponía una frecuencia de 50Hz (60Hz) en los
Amiga del mercado estadounidense). El retrazo vertical es el recorrido que hace el rayo catódico del tubo
de imagen del monitor cuando viaja desde la esquina inferior derecha hasta la superior izquierda, para
empezar a dibujar una nueva imagen. Mientras sucede no se dibuja nada en la pantalla. En cuanto se
inicia se dispara dicha interrupción, que suele utilizarse para dibujar en la memoria de pantalla de tal
manera que cuando la nueva imagen empieza a dibujarse en el monitor ya está completa en la RAM de
video por lo que no se aprecian discontinuidades o parpadeos durante una animación.
Aunque la tarjeta de sonido usada en el proyecto nos proporciona una linea de interrupción
dedicada a la emulación de la DMA, y podríamos usar el timer del PC para esta tarea, hemos preferido
no usar éste, sino aprovechar la “señal” de interrupción de “fin de DMA” que origina el emulador para
instalar en ella la rutina que calcula los efectos y lee una nueva división.
Haremos, pues, que el tiempo de la transferencia de un bloque por la DMA emulada tarde lo
mismo, sea cual sea la frecuencia de muestreo. Para ello hemos de calcular previamente cuál será la
longitud de este bloque. La fórmula es:
O sea, el número de muestras que se leerán en 1/50 de segundo. El emulador de DMA dispone
de un contador de muestras enviadas al puerto paralelo. Cuando esta cuenta acabe se producirá la
condición de “fin de DMA”. Entonces se procederá a llamar a la rutina prep_datos. Esta rutina realiza
las siguientes tareas:
T
Inicializa los contadores DMA para una nueva transferencia.
T
Comprueba si el módulo se ha terminado, y no continua si es así.
T
Realiza una llamada a la rutina swap_bloque que intercambia entre sí la posición de dos bloques
de memoria. Uno de ellos será apuntado por el puntero bloque_llena y es el bloque que va a ser llenado
con las muestras calculadas durante el proceso de mezcla (el bucle interno del intérprete MOD) y que
acaba de ser transferido al puerto paralelo. El otro es el bloque que va ser transferido al puerto paralelo,,
y que acaba de ser relleno con los datos de la última ejecución del bucle de mezcla. Será apuntado por
bloque_dma. Por supuesto, no son los contenidos los que se intercambian, sino los punteros. Con este
mecanismo de doble buffering no se pierde continuidad en la audición del módulo.
T
Llama a la rutina llenar_dma para rellenar con muestras el contenido del bloque al que ahora
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.10
apunta ‘bloque_llena’.
T
Por último llama a la rutina calc_efecto que, a partir de los datos almacenados en la estructura
de cada canal variará los valores de tono y/o volumen de la nota actual tal y como se describe en la
especificación MOD.
La rutina calc_efecto llama cuatro veces a una macro con un parámetro correspondiente al número
de cada canal del módulo. Después actualiza un contador de ticks y, si ese contador ha llegado al número
especificado de ticks por división (ver efecto 15) se vuelve a poner a 0 y se realiza una llamada a la rutina
actualiza. Esta rutina leerá del patrón actual el número de división que viene a continuación. Si la
anterior fue la última, o se recibió un efecto 11 o 13 se leerá de la lista de patrones el número del que
viene a continuación. Ese número de usará como índice a la tabla de patrones cuyas entradas son punteros
a cada uno de los bloques de memoria que almacenan los patrones. La dirección del patón actual se lee
y se pone el contador de divisiones a 0.
La actualización de cada canal la lleva a cabo la macro act_canal que recibe un parámetro como
en calc_efecto. Esta macro extrae la información almacenada en la división actual para ese canal (periodo
de la nota, instrumento y efectos) y actualiza el contenido de las estructuras muestra1 a muestra4 .
El listado siguiente corresponde a los fuentes de las rutinas encargadas todas las tareas descritas
aquí. La rutina de cálculo de efectos se entiende mejor habiendo leído las especificaciones de los MOD’s,
en el capítulo 3.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
act_canal
Pag. 7.11
macro canal
local hayinfo,noponnota,noponins,no_veloc,novol,noup,nodwn
local slid_dwn,noslide,nada,noarpegio,hayefecto,pon_tpd
local noromper,nosalto,nooffset,notslide,es_slideu
local siguetono1,siguetono2,siguetono3,calc_arp1,calc_arp2
local no_arp1,no_arp2,noact_ins,haz_retrig,hay_numins,mirar0
local nospecial,nosfvolup,nosfvoldo,pon_beat
;Borramos los flags que indican que hay efectos en este canal
mov tab_muest&canal.flag_slide,0
mov tab_muest&canal.flag_tslided,0
mov tab_muest&canal.flag_tslideu,0
mov tab_muest&canal.flag_arpegio,0
mov tab_muest&canal.flag_pitch,0
mov si,es:[bx]
or si,es:[bx+2]
or si,es:[bx+4]
jnz hayinfo
jmp nada
hayinfo:
mov si,es:[bx]
or si,si
jz noponnota
;si el campo nota es 0, no hagas nada
cmp byte ptr es:[bx+3],cod_tono
je noponnota
;lo mismo si el efecto es ‘slide to note’.
push bx
mov bx,offset frec2offs
mov tab_muest&canal.pitch,si
add si,si
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
;Guarda el nuevo valor de baseta-
bla
pop bx
noponnota:
mov al,es:[bx+2]
or al,al
jnz hay_numins
cmp word ptr es:[bx],0
jz noponins
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.12
mov al,tab_muest&canal.num_ins
hay_numins:
mov tab_muest&canal.num_ins,al
dec al
mov dl,42
;longitud de un elemento de la tabla de instrumentos
mul dl
add ax,offset tab_ins
xor dl,dl
cmp word ptr es:[bx],0
jne haz_retrig
cmp byte ptr es:[bx+3],0
je haz_retrig
mov dl,1
haz_retrig:
push bx
mov bx,ax
;bx -> instrumento elegido
mov ax,[bx].volum_ins
mov tab_muest&canal.volumen,ax
;Guarda volumen del instrumento
or dl,dl
jnz noact_ins
mov eax,[bx].base_ins
mov tab_muest&canal.pri_muest,eax
;Guarda offset a la primera pos.
mov ecx,[bx].loop_s
add ecx,eax
mov tab_muest&canal.loopsm,ecx
;Guarda offset del principio del
loop
mov ecx,[bx].long_ins
dec ecx
mov eax,tab_muest&canal.pri_muest
add eax,ecx
mov tab_muest&canal.fin_muest,eax
;Guardar offset del final de la
muestra
mov eax,[bx].loop_l
add eax,tab_muest&canal.loopsm
mov tab_muest&canal.looplm,eax
noact_ins:
pop bx
noponins:
mov ax,es:[bx+3]
;Guarda offset del final del loop
or ax,ax
jnz hayefecto
jmp nada
hayefecto:
cmp al,cod_veloc
;si es el codigo de velocidad
jne no_veloc
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.13
cmp ah,32
jb mirar0
jmp nada
mirar0:
;si es >=32, son beats/minuto
or ah,ah
jz nada
jmp pon_tpd
;pon_beat:
mov bl,ah
;
mov ax,750
;
div bl
;
mov ah,al
pon_tpd:
mov velocidad,ah
mov cont_tpd,ah
jmp nada
no_veloc:
cmp al,cod_volum
;si es código de volumen
jne novol
mov al,ah
;lee el volumen
xor ah,ah
mov tab_muest&canal.volumen,ax
jmp nada
novol:
cmp al,cod_pitchup
;slide up
jne noup
mov tab_muest&canal.flag_pitch,1
mov al,ah
xor ah,ah
mov tab_muest&canal.valor_pitch,ax
jmp nada
noup:
cmp al,cod_pitchdo
;slide down
jne nodwn
mov tab_muest&canal.flag_pitch,1
mov al,ah
xor ah,ah
neg ax
mov tab_muest&canal.valor_pitch,ax
jmp nada
nodwn:
cmp al,cod_vslide
;volume slide
jne noslide
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.14
mov tab_muest&canal.flag_slide,1
mov al,ah
test al,0f0h
jz slid_dwn
and al,0f0h
sar al,4
xor ah,ah
mov tab_muest&canal.valor_slide,ax
jmp nada
slid_dwn:
xor ah,ah
neg ax
mov tab_muest&canal.valor_slide,ax
jmp nada
noslide:
cmp al,cod_arpegio
jne noarpegio
mov tab_muest&canal.flag_arpegio,1
mov cl,ah
mov ax,tab_muest&canal.pitch
sar cl,4
and cl,0fh
jz no_arp1
xor ch,ch
calc_arp1:
mov si,32768
mul si
mov si,34716
div si
;en cada vuelta del bucle se divide DX:AX / 2^(1/12)
loop calc_arp1
;este número es la razón que hay entre la frecuencia
de
;un semitono y el siguiente en la escala musical.
no_arp1:
mov tab_muest&canal.arpegio1,ax
mov ax,tab_muest&canal.pitch
mov cl,es:[bx+4]
and cl,0fh
jz no_arp2
xor ch,ch
calc_arp2:
mov si,32768
mul si
mov si,34716
div si
loop calc_arp2
no_arp2:
mov tab_muest&canal.arpegio2,ax
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.15
jmp nada
noarpegio:
cmp al,cod_break
; si es el codigo de romper patron
jne noromper
mov hacersalto,1
jmp nada
noromper:
cmp al,cod_salto
jne nosalto
mov al,ah
xor ah,ah
mov cont_pat,ax
mov hacersalto,1
jmp nada
nosalto:
cmp al,cod_offset
jne nooffset
xor eax,eax
mov ah,es:[bx+4] ;efecto
add eax,tab_muest&canal.pri_muest
cmp eax,tab_muest&canal.fin_muest
ja nooffset
mov tab_muest&canal.pri_muest,eax
jmp nada
nooffset:
cmp al,cod_tono
;slide to note
jne notslide
mov ax,es:[bx]
or ax,ax
jnz siguetono1
mov ax,tab_muest&canal.finslide
siguetono1:
mov tab_muest&canal.finslide,ax
cmp ax,tab_muest&canal.pitch
jbe es_slideu
mov tab_muest&canal.flag_tslided,1
jmp siguetono3
es_slideu:
mov tab_muest&canal.flag_tslideu,1
siguetono3:
mov al,es:[bx+4]
or al,al
jnz siguetono2
mov al,tab_muest&canal.valefecto
siguetono2:
mov tab_muest&canal.valefecto,al
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.16
xor ah,ah
mov tab_muest&canal.valtslide,ax
jmp nada
notslide:
cmp al,cod_special
;efectos tipo 14
jne nospecial
mov al,ah
sar al,4
and ax,0f0fh
cmp al,cod_sfvolup
;fine volume up
jne nosfvolup
cmp byte ptr tab_muest&canal.volumen,64
je nosfvolup
add byte ptr tab_muest&canal.volumen,ah
jmp nada
nosfvolup:
cmp al,cod_sfvoldo
;fine volume down
jne nosfvoldo
cmp byte ptr tab_muest&canal.volumen,0
je nosfvoldo
sub byte ptr tab_muest&canal.volumen,ah
jmp nada
nosfvoldo:
nospecial:
nada:
add bx,6
endm
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
efectos
Pag. 7.17
macro canal
local nopitch,noslide,noarpegio,notslide,nofin_u,nofin_d
local final,mayor113,menor856,menor64,mayor0,notslideu
local notslided
cmp tab_muest&canal.flag_pitch,0
jz nopitch
mov ax,tab_muest&canal.pitch
sub ax,tab_muest&canal.valor_pitch
cmp ax,113
jge mayor113
mov ax,tab_muest&canal.pitch
mayor113:
cmp ax,856
jle menor856
mov ax,tab_muest&canal.pitch
menor856:
mov si,ax
mov tab_muest&canal.pitch,ax
add si,si
mov bx,offset frec2offs
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
jmp final
nopitch:
cmp tab_muest&canal.flag_slide,0
jz noslide
mov ax,tab_muest&canal.volumen
add ax,tab_muest&canal.valor_slide
cmp ax,64
jle menor64
mov ax,64
menor64:
cmp ax,0
jge mayor0
xor ax,ax
mayor0:
mov tab_muest&canal.volumen,ax
mul byte ptr volumen&canal
shr ax,6
mov tab_muest&canal.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest&canal.vol_tabla,ax
jmp final
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
noslide:
Pag. 7.18
cmp tab_muest&canal.flag_arpegio,0
jz noarpegio
mov ax,tab_muest&canal.pitch
mov si,tab_muest&canal.arpegio1
mov tab_muest&canal.pitch,si
mov bx,tab_muest&canal.arpegio2
mov tab_muest&canal.arpegio1,bx
mov tab_muest&canal.arpegio2,ax
add si,si
mov bx,offset frec2offs
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
jmp final
noarpegio:
cmp tab_muest&canal.flag_tslideu,0
jz notslideu
mov si,tab_muest&canal.pitch
sub si,tab_muest&canal.valtslide
cmp si,tab_muest&canal.finslide
ja nofin_u
mov si,tab_muest&canal.finslide
mov tab_muest&canal.flag_tslideu,0
nofin_u:
mov tab_muest&canal.pitch,si
add si,si
mov bx,offset frec2offs
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
jmp final
notslideu:
cmp tab_muest&canal.flag_tslided,0
jz notslided
mov si,tab_muest&canal.pitch
add si,tab_muest&canal.valtslide
cmp si,tab_muest&canal.finslide
jb nofin_d
mov si,tab_muest&canal.finslide
mov tab_muest&canal.flag_tslided,0
nofin_d:
mov tab_muest&canal.pitch,si
add si,si
mov bx,offset frec2offs
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.19
jmp final
notslided:
final:
endm
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
prep_datos
Pag. 7.20
proc near
push eax
push ebx
push ecx
push edx
push esi
push edi
push ebp
push fs
cld
inc conta_frames
cmp terminado,0
jne fin_prep
cmp fin_canc,0
jne fin_tprep
mov ax,bytes_trans
mov cont_int,ax
mov indice_int,0
call swap_bloque
xor ax,ax
mov fs,ax
sti
call llenar_dma
call calc_efecto
cli
jmp fin_prep
fin_tprep:
mov terminado,1
fin_prep:
pop fs
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
ret
prep_datos
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.21
actualiza
proc near
actualiz:
mov chivato,1
;se va a leer una nueva división.
cmp hazpausa,1
;si vale 1, se congela la lectura de nuevas
divisiones
jne nopausa
ret
nopausa:
cmp hacersalto,1
jne nohazsalto
mov hacersalto,0
jmp cambpat
nohazsalto:
inc cont_lin
cmp cont_lin,64
jne nocambpat
jmp cambpat
nocambpat:
mov ax,patr_act
mov es,ax
;es direcciona el nuevo patron
mov bx,linea_act
;bx se va moviendo a traves del patron
call actual_canal
mov linea_act,bx
call ponvolumen
ret
cambpat:
mov cont_lin,255
mov bx,offset lis_patt
mov si,cont_pat
inc cont_pat
mov al,[bx+si]
;leer el nº de patron que sigue en la lista
cmp al,128
je fintocar
mov bl,4
;tamaño de un elemento de la tabla de punteros a patrones
mul bl
mov bx,ax
add bx,offset tab_patt ;bx -> puntero al patron a tocar
mov dx,[bx]
;dx=offset del nuevo patron
mov linea_act,dx
mov dx,[bx+2]
;dx=segmento del nuevo patron
mov patr_act,dx
jmp actualiz
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
fintocar:
Pag. 7.22
mov fin_canc,1
ret
actualiza
endp
actual_canal proc near
act_canal 1
act_canal 2
act_canal 3
act_canal 4
ret
actual_canal endp
calc_efecto
proc near
efectos 1
efectos 2
efectos 3
efectos 4
dec cont_tpd
jnz no_llam_act
mov al,velocidad
mov cont_tpd,al
jmp actualiza
no_llam_act: ret
calc_efecto
endp
ponvolumen
proc C
mov al,byte ptr tab_muest1.volumen
mul volumen1
shr ax,6
mov tab_muest1.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest1.vol_tabla,ax
mov al,byte ptr tab_muest2.volumen
mul volumen2
shr ax,6
mov tab_muest2.vol_play,ax
shl ax,8
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.23
add ax,offset tabla_g_vol
mov tab_muest2.vol_tabla,ax
mov al,byte ptr tab_muest3.volumen
mul volumen3
shr ax,6
mov tab_muest3.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest3.vol_tabla,ax
mov al,byte ptr tab_muest4.volumen
mul volumen4
shr ax,6
mov tab_muest4.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest4.vol_tabla,ax
ret
ponvolumen
endp
swap_bloque
proc near
mov eax,bloque_dma
xchg eax,bloque_lle
mov bloque_dma,eax
ret
swap_bloque
endp
llenar_mono
proc near
push ebp
canal4_mono
pop ebp
ret
llenar_mono
endp
llenar_ste
proc near
push ebp
canal4_st
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.24
pop ebp
ret
llenar_ste
endp
llenar_dma
proc near
cmp disp_salida,SBP_ST
je es_ste
cmp disp_salida,PROY
je es_ste
jmp llenar_mono
es_ste:
jmp llenar_ste
llenar_dma
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.25
7.2.- Listado fuente de la biblioteca de rutinas para cargar y
ejecutar MOD’s
El conjunto de rutinas mostradas a continuación permiten al usuario cargar y ejecutar archivos
MOD usando las técnicas comentadas hasta ahora.
La biblioteca soporta varios dispositivos de salida, aunque en este trabajo se ha hecho hincapié
en la emulación de DMA y la tarjeta de sonido proyectada para el puerto paralelo.
Los dispositivos soportados son: altavoz interno, DAC simple en el puerto paralelo, tarjeta de
proyecto, Sound Blaster 2.0 y Sound Blaster Pro.
Se incluye además el fuente de un programa de demostración que hace uso de esta biblioteca,
hecho enteramente en C. No se incluirán las rutinas del gestor de memoria que son las que se han
listado en el capítulo 5.
Los módulos listados son:
TRACKLIB.H
Archivo de cabecera para poder usar la biblioteca en las aplicaciones de
usuario.
TRACKLD.C
Módulo que se encarga de la inicialización del sistema, carga del módulo y
ajuste de parámetros del mismo.
TRACKEJC.ASM Módulo encargado de la reproducción del archivo MOD.
SECUENC.INC
Archivo de inclusión para TRACKEJC.ASM que contiene las secuencias
generadas por el algoritmo de Bresenham para cada nota del rango soportado por los archivos MOD.
COMPRES.INC
Archivo de inclusión con una tabla para traducir valores de muestras a valores
apropiados para el altavoz interno. Esta tabla contiene las imágenes de una función que, aplicada a los
valores de un instrumento PCM devuelve otra lista de valores modificados de tal forma que las
muestras con bajo volúmen se amplifican más que las que tienen un volumen más alto. Así la energía
que produce el altavoz interno en la reproducción es la necesaria para que se oiga el sonido con un
cierto volumen sin llegar a la distorsión.
TRPLAY.C
Fuente de ejemplo de uso de las funciones de biblioteca.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.26
TRACKLIB.H
#if __STDC__
#define _Cdecl
#else
#define _Cdecl
cdecl
#endif
#if
!defined(__TRACKLIB)
#define __TRACKLIB
#endif
#if
!defined(__STDIO_H)
#include <stdio.h>
#endif
enum
SALIDA {ALTAVOZ=0, DAC_LPT, PROY, SB20, SBP_MONO, SBP_ST, NULO=255};
enum
{NTSC=0, PAL};
enum
{LPT1,LPT2,LPT3};
/* Estas son las variables comunes a los dos módulos de C y ensamblador */
struct st_ins
{
char nombre_ins[22];
unsigned long_ins;
unsigned volum_ins;
unsigned loop_s;
unsigned loop_l;
unsigned long base_ins;
int mcb;
};
typedef struct st_ins TINS;
struct st_muest
{
int filler1;
unsigned fin_muest;
unsigned pri_muest;
unsigned seg_muest;
unsigned looplm;
unsigned loopsm;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.27
unsigned basetabla;
unsigned volumen;
unsigned vol_play;
unsigned valor;
unsigned pitch;
unsigned valor_slide;
unsigned arpegio1;
unsigned arpegio2;
char num_ins;
char flag_pitch;
char flag_slide;
char flag_arpegio;
};
typedef struct st_muest TMUESTRA;
extern char
*tab_patt[128];
extern char
lis_patt[128];
extern TINS
tab_ins[31];
extern char
nombremod[22];
extern char
disp_salida;
extern char
chivato;
extern char
hacersalto;
extern char
hazpausa;
extern volatile char cont_lin;
extern volatile unsigned cont_pat;
extern char
terminado;
extern char
volumen1;
extern char
volumen2;
extern char
volumen3;
extern char
volumen4;
extern unsigned frecuencia;
extern volatile char velocidad;
extern volatile char cont_tpd;
extern volatile unsigned conta_frames;
extern char
*bloque_dma;
extern char
*bloque_lle;
extern unsigned sb_puerto;
extern char
sb_int;
extern char
sb_dma;
extern char
sb_time;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.28
extern unsigned lptdata;
extern unsigned lptstd;
extern unsigned lptctrl;
extern TMUESTRA tab_muest1;
extern TMUESTRA tab_muest2;
extern TMUESTRA tab_muest3;
extern TMUESTRA tab_muest4;
int
_Cdecl detecta_SB
(void);
char
_Cdecl parametros_SB
(void);
void
_Cdecl cambia_frecuencia
(char, char);
void
_Cdecl init_sampler
(void);
void
_Cdecl des_sampler
(void);
int
_Cdecl cargar_modulo
(FILE *);
void
_Cdecl borrar_modulo
(void);
unsigned
_Cdecl detecta_LPT
(int);
unsigned
_Cdecl detecta_proy
(void);
char
_Cdecl prepara_doble_buffer (void);
void
_Cdecl prepara_tabla_vol
(char);
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.29
TRACKLD.C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "xmem.h"
#define BREAK
0x0d
#define VOLUMEN
0x0c
#define VELOCIDAD
0x0f
#define SALTO
0x0b
#define PITCHUP
0x01
#define PITCHDOWN
0x02
#define TONO
0x03
#define VSLIDE
0x0a
#define SOFFSET
0x09
#define ALTAVOZ
0
#define DAC_LPT
1
#define PROY
2
#define SB20
3
#define SBP_MONO
4
#define SBP_ST
5
char nombremod[22];
/* nombre del módulo */
unsigned frec2offs[744];
char tabla_g_vol[65][256];
struct st_ins
{
char nombre_ins[22];
unsigned long long_ins;
unsigned long loop_s;
unsigned long loop_l;
unsigned long base_ins;
unsigned volum_ins;
int mcb;
};
struct hd_ins
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.30
{
char nombre_ins[22];
unsigned long_ins;
unsigned volum_ins;
unsigned loop_s;
unsigned loop_l;
};
/* Estas son las variables comunes a los dos módulos de C y ensamblador */
char *tab_patt[128];
char lis_patt[128];
struct st_ins tab_ins[31];
char disp_salida;
char velocidad;
char terminado;
char hazpausa;
char hacersalto;
extern unsigned int tabla_bres;
unsigned sb_puerto;
char sb_int;
char sb_dma;
char sb_time;
char *bloque_dma;
char *bloque_lle;
char volumen1,volumen2,volumen3,volumen4;
char cont_lin;
unsigned cont_pat;
char chivato;
unsigned bytes_trans;
unsigned conta_frames;
char periodo,perproy;
unsigned frecuencia;
unsigned periodo_ant08;
unsigned lptdata,lptstd,lptctrl;
char numintp;
void moto2intel(unsigned *numero)
/* Eata función convierte un entero de 2 bytes del formato de Motorola al de
Intel, y viceversa */
{
char alto,bajo;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.31
bajo=*numero/256;
alto=*numero%256;
*numero=alto*256+bajo;
}
unsigned detecta_LPT (int);
void e8253 (char, char, char);
int reset_proy (void)
{
char estado,cambio;
unsigned i;
e8253(1,1,0x38);
e8253(0,0,0);
/* Silenciar DAC's */
e8253(0,0,0);
e8253(1,1,0x74);
e8253(0,1,0x9b);
e8253(0,1,0x4);
/* Programamos el timer del ADC para 1000Hz */
outp(lptctrl,3); /* Deshabilitar todos los dispositivos */
for (i=0,cambio=0;i<5000;i++)
{
estado=inp(lptstd);
if (estado&0x40)
cambio=1;
else if (cambio==1)
cambio=2;
if (cambio==2)
break;
}
e8253(1,1,0x78);
/* Silenciar ADC */
e8253(0,1,0);
e8253(0,1,0);
return (cambio==2);
}
unsigned detecta_proy (void)
{
detecta_LPT (0);
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.32
if (lptdata!=0 && reset_proy())
{
numintp=(lptdata==0x278)? 0xd : 0xf;
return lptdata;
}
detecta_LPT (1);
if (lptdata!=0 && reset_proy())
{
numintp=(lptdata==0x278)? 0xd : 0xf;
return lptdata;
}
detecta_LPT (2);
if (lptdata!=0 && reset_proy())
{
numintp=(lptdata==0x278)? 0xd : 0xf;
return lptdata;
}
return 0;
}
void lee_sample (FILE *modulo, unsigned long longitud, int mcb)
{
char *ptins;
unsigned long offset=0L;
int num_lectur=longitud/32768L;
unsigned ultima_lectur=longitud%32768L;
int i;
ptins=malloc(32768);
for (i=0;i<num_lectur;i++)
{
fread(ptins,1,32768,modulo);
X_escribir(ptins,mcb,offset,32768L);
offset+=32768L;
}
if (ultima_lectur)
{
fread(ptins,1,ultima_lectur,modulo);
X_escribir(ptins,mcb,offset,(unsigned long)ultima_lectur);
}
free(ptins);
}
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.33
int cargar_modulo (FILE *modulo)
/*
Carga un módulo en memoria.
Devuelve:
0 ----> Carga efectuada con normalidad.
1 ----> No se pudo encontrar el módulo.
2 ----> Error cargando módulo. Formato erróneo.
3 ----> Formato de módulo erróneo (sample>64K).
4 ----> No hay memoria suficiente para cargar el módulo
*/
{
char tiempo;
/* tiempo leído del fichero */
char long_lista;
/* longitud de la lista de patrones */
char num_pat;
/* nº de patrones que hay almacenados */
char i;
unsigned j;
char *ppatron,*pfuente,*pdestino;
unsigned nota;
char flag31;
unsigned long posic_fichero;
struct hd_ins hd_instru;
memset(tab_ins,0,sizeof(tab_ins));
memset(tab_patt,0,sizeof(tab_patt));
posic_fichero=ftell(modulo);
fseek(modulo,1080,SEEK_CUR);
fread(nombremod,1,4,modulo);
nombremod[4]=NULL;
fseek(modulo,posic_fichero,SEEK_SET);
if (!strcmp(nombremod,"M.K.") || !strcmp(nombremod,"FLT4"))
flag31=16;
else
flag31=0;
if (fread(nombremod,1,20,modulo)<20)
return 2;
for (i=0;i<15+flag31;i++)
{
if (fread(&hd_instru,1,30,modulo)<30)
return 2;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.34
memcpy(tab_ins[i].nombre_ins,hd_instru.nombre_ins,22);
moto2intel(&hd_instru.long_ins);
tab_ins[i].long_ins=hd_instru.long_ins;
moto2intel(&hd_instru.volum_ins);
tab_ins[i].volum_ins=hd_instru.volum_ins;
moto2intel(&hd_instru.loop_s);
tab_ins[i].loop_s=hd_instru.loop_s;
moto2intel(&hd_instru.loop_l);
tab_ins[i].loop_l=hd_instru.loop_l;
tab_ins[i].loop_s*=2;
tab_ins[i].loop_l*=2;
if (tab_ins[i].loop_l)
tab_ins[i].loop_l--;
if (tab_ins[i].long_ins>3)
{
tab_ins[i].long_ins*=2;
tab_ins[i].mcb=X_malloc(tab_ins[i].long_ins);
if (tab_ins[i].mcb<0)
return 4;
tab_ins[i].base_ins=X_direccion(tab_ins[i].mcb);
}
else
tab_ins[i].mcb=-1;
}
fread(&long_lista,1,1,modulo);
fread(&tiempo,1,1,modulo);
if (!tiempo)
tiempo=120;
velocidad=tiempo/20;
if (!velocidad)
velocidad=1;
if (fread(lis_patt,1,128,modulo)<128)
return 2;
num_pat=0;
for (i=0;i<127;i++)
if (lis_patt[i]>num_pat)
num_pat=lis_patt[i];
num_pat++;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.35
for (i=127;i>=0;i--)
if (lis_patt[i]!=0)
break;
if (long_lista<i)
long_lista=i;
lis_patt[long_lista]=128;
if (flag31)
fseek(modulo,4,SEEK_CUR);
ppatron=(char *) malloc(1024);
for (i=0;i<num_pat;i++)
{
tab_patt[i]=(char *) malloc(1536);
if (!(tab_patt[i]))
return 4;
if (fread(ppatron,1024,1,modulo)<1)
return 2;
for
(j=0,pfuente=ppatron,pdestino=tab_patt[i];j<256;j++,pfuente+=4,pdestino+=6)
{
nota=*( (unsigned *)pfuente);
moto2intel(&nota);
if (nota>=0x1000)
{
nota&=0xfff;
pdestino[2]=16;
}
else
pdestino[2]=0;
*( (unsigned *)pdestino)=nota;
pdestino[2]+=(pfuente[2]>>4)&0xf;
pdestino[3]=pfuente[2]&0xf;
if (pdestino[3]==TONO && pfuente[3]>112)
pfuente[3]=112;
if (pdestino[3]==PITCHUP && pfuente[3]>112)
pfuente[3]=112;
pdestino[4]=pfuente[3];
pdestino[5]=0;
}
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.36
}
free(ppatron);
for (i=0;i<15+flag31;i++)
if (tab_ins[i].long_ins)
lee_sample(modulo,tab_ins[i].long_ins,tab_ins[i].mcb);
return 0;
}
void borrar_modulo(void)
{
char i;
for(i=0;i<31;i++)
if (tab_ins[i].mcb>=0)
X_free(tab_ins[i].mcb);
for(i=0;i<63;i++)
if (tab_patt[i])
free(tab_patt[i]);
}
void cambia_frecuencia(char letra, char pal)
{
float frec;
float base;
float valor_off,incrm;
unsigned indoff,desde,hasta;
int i,j;
unsigned tabla[36]={856,808,762,720,678,640,604,570,538,508,480,453,
428,404,381,360,339,320,302,285,269,254,240,226,
214,202,190,180,170,160,151,143,135,127,120,113 };
disable();
letra&=0xdf;
if (letra<'A' || letra>'X')
letra='L';
valor_off=(float) (tabla_bres+(letra-'A')*256.0);
base=(pal==0)? 7159090.5 : 7093789.2;
frec=base/226;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.37
for (i=0;i<letra-'A';i++)
frec=frec/1.0594631;
sb_time = (char) (65536.0 - 256000000.0 /
(frec*(2*(disp_salida==SBP_ST)+(disp_salida!=SBP_ST)))/256.0);
bytes_trans=(1+(unsigned)((frec/51)+0.5))&0xfffe;
periodo=(char) (1193180/frec);
perproy=(char) (1179243.75/frec);
periodo_ant08=(unsigned) (frec/18.2);
frecuencia=(unsigned) frec;
if (disp_salida==SBP_ST || disp_salida==PROY)
bytes_trans*=2;
indoff=743;
for (i=0;i<35;i++)
{
desde=tabla[i];
hasta=tabla[i+1];
incrm=(float) (256.0/(tabla[i]-tabla[i+1]));
for (j=desde;j>hasta;j--)
{
frec2offs[indoff--]=(unsigned int) valor_off;
valor_off=valor_off+incrm;
}
}
frec2offs[indoff]=(unsigned int) valor_off;
enable();
}
void asigna_mem_sb (char **bloque)
{
*bloque=(char *) malloc(4096);
*bloque=(char *) MK_FP (FP_SEG (*bloque) + FP_OFF (*bloque)/16 +1,0);
while (FP_SEG(*bloque) & 0x00FF)
*bloque=(char *) MK_FP (FP_SEG(*bloque)+1,0);
}
int
parametros_SB (void)
{
char *entorno;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.38
char *dma,*intr;
entorno=getenv("BLASTER");
if (!entorno)
return 0;
strupr(entorno);
dma=strstr(entorno,"D");
intr=strstr(entorno,"I");
if (!dma || !intr)
return 0;
sb_dma=dma[1]-'0';
sb_int=8+intr[1]-'0';
if (sb_int==1)
return 0;
return 1;
}
char prepara_doble_buffer (void)
{
if (!bloque_dma && !bloque_lle)
{
asigna_mem_sb (&bloque_dma);
asigna_mem_sb (&bloque_lle);
}
return (bloque_dma || bloque_lle);
}
void prepara_tabla_vol (char ncanales)
{
int vol,sample,muestra;
for (vol=0;vol<=64;vol++)
for (sample=0;sample<256;sample++)
{
muestra=(signed char) (sample);
tabla_g_vol[vol][sample]=((muestra*vol)>>6)/ncanales;
}
}
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.39
TRACKEJC.ASM
comment %
MODULO OBJETO EN ENSAMBLADOR PARA EL PROGRAMA PROCESADOR DE MODULOS DE
TRACKER.
Especificaciones:
----------------- Modelo de memoria: large
- Lenguaje de llamada: C (Turbo C)
- Procesador: 80386+
%
.model large
.286
;Esta macro espera hasta que el DSP de la Sound Blaster esté listo para aceptar
comandos
espera_esc
macro
local esp_esc
mov dx,sb_puerto
esp_esc:
in al,dx
test al,80h
jnz esp_esc
endm
;Esta macro espera hasta que el DSP tenga el dato a leer listo
espera_lec
macro
local esp_lec
mov dx,sb_puerto
add dx,2
esp_lec:
in al,dx
test al,80h
jz esp_lec
sub dx,4
endm
;Los dispositivos de salida digital que soporta el programa
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
ALTAVOZ
equ 0
DAC_LPT
equ 1
PROY
equ 2
SB20
equ 3
SBP_MONO
equ 4
SBP_ST
equ 5
Pag. 7.40
;Los comandos (subconjunto de los soportados en el Amiga Protraker)
cod_break
equ 0dh
cod_volum
equ 0ch
cod_veloc
equ 0fh
cod_pitchup
equ 01h
cod_pitchdo
equ 02h
cod_tono
equ 03h
cod_salto
equ 0bh
cod_vslide
equ 0ah
cod_arpegio
equ 00h
cod_offset
equ 09h
cod_vibrato
equ 04h
cod_tonvsli
equ 05h
cod_special
equ 0eh
cod_sfvolup
equ 0ah
cod_sfvoldo
equ 0bh
.data
;Registro para cada uno de los 31 instrumentos
st_ins
struc
nombre_ins
db 22 dup(?)
long_ins
dd ?
loop_s
dd ?
loop_l
dd ?
base_ins
dd ?
volum_ins
dw ?
mcb
dw ?
st_ins
ends
;Puntero a cada partón
st_patt
struc
dd ?
st_patt
ends
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.41
;Registro para cada canal
st_muest
struc
fin_muest
dd 1
; Dirección lineal de la última
dd 0
; Dirección lineal de la próxima
dd 1
; Dirección lineal de la última
muestra
pri_muest
muestra
looplm
muestra del loop
loopsm
dd 0
; Dirección lineal de la primera
muestra del loop
basetabla
dw 0
; Offset relativo a DS de la tabla de
incrementos para este canal
volumen
dw 0
; Volúmen (de 0 a 64) definido por el
vol_play
dw 0
; volumen*volumen_general_canal/256
vol_tabla
dw 0
; Offset relativo a DS de la tabla de
módulo
volúmenes para el valor actual de vol_play
pitch
dw 0
valor_slide
dw 0
arpegio1
dw 0
arpegio2
dw 0
valtslide
dw 0
finslide
dw 0
valor_pitch
dw 0
num_ins
db 0
valefecto
db 0
; Valor del comando leído para este
flag_pitch
db 0
;
flag_slide
db 0
canal
flag_arpegio db 0
flag_tslided db 0
flag_tslideu db 0
st_muest
ends
extrn C tab_ins:st_ins:31
extrn C tab_patt:st_patt:128
extrn C lis_patt:byte:128
extrn C terminado:byte
extrn C velocidad:byte
extrn C cont_lin:byte
;Contador de lineas de patron leidas
extrn C cont_pat:word
;Contador de patrones leídos
extrn C volumen1:byte
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
extrn C volumen2:byte
Pag. 7.42
;mascaras para silenciar cada canal
extrn C volumen3:byte
extrn C volumen4:byte
extrn C chivato:byte
extrn C disp_salida:byte
;Salida por altavoz, por D/A o por SB
extrn C hazpausa:byte
extrn C hacersalto:byte
extrn C conta_frames:word
extrn C frec2offs:word:744
;Tabla de trad. entre frecuencias
Amiga y offsets en la tabla de Bresenham
extrn C tabla_g_vol:byte:16640 ;Tabla de volumenes
br_indice
dw 0
patr_act
dw 0
;Solo el segmento
linea_act
dw 0
;Offset dentro del patron actual
;Variables de uso de la Sound Blaster
extrn C bloque_dma:dword
extrn C bloque_lle:dword
extrn C sb_puerto:word
extrn C sb_int:byte
extrn C sb_dma:byte
extrn C sb_time:byte
extrn C bytes_trans:word
offdsp
dw 0
segdsp
dw 0
;Variables de uso del altavoz interno y el DAC
extrn C periodo:byte
extrn C perproy:byte
extrn C lptdata:word
extrn C lptctrl:word
extrn C lptstd:word
extrn C numintp:byte
extrn C periodo_ant08:word
cont_ant08
dw 0
indice_int
dw 0
cont_int
dw 0
ant08
dd 0
antproy
dd 0
evendata
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
tab_muest1
Pag. 7.43
st_muest <>
evendata
tab_muest2
st_muest <>
;Tabla de muestras para
st_muest <>
;los 4 canales
evendata
tab_muest3
evendata
tab_muest4
st_muest <>
evendata
fin_canc
db 0
cont_tpd
db 0
public C cont_tpd
public C tab_muest1
public C tab_muest2
public C tab_muest3
public C tab_muest4
public C tabla_bres
include secuenc.inc
include compres.inc
; Valores de la tabla de incrementos
; Valores de la tabla de traducción
muestra->altavoz
.code player_tracker
.386
public C init_sampler
public C des_sampler
public C ponvolumen
public C detecta_SB
public C detecta_LPT
public C e8253
act_canal
macro canal
local hayinfo,noponnota,noponins,no_veloc,novol,noup,nodwn
local slid_dwn,noslide,nada,noarpegio,hayefecto,pon_tpd
local noromper,nosalto,nooffset,notslide,es_slideu
local siguetono1,siguetono2,siguetono3,calc_arp1,calc_arp2
local no_arp1,no_arp2,noact_ins,haz_retrig,hay_numins,mirar0
local nospecial,nosfvolup,nosfvoldo,pon_beat
mov tab_muest&canal.flag_slide,0
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.44
mov tab_muest&canal.flag_tslided,0
mov tab_muest&canal.flag_tslideu,0
mov tab_muest&canal.flag_arpegio,0
mov tab_muest&canal.flag_pitch,0
mov si,es:[bx]
or si,es:[bx+2]
or si,es:[bx+4]
jnz hayinfo
jmp nada
hayinfo:
mov si,es:[bx]
or si,si
jz noponnota
cmp byte ptr es:[bx+3],cod_tono
je noponnota
push bx
mov bx,offset frec2offs
mov tab_muest&canal.pitch,si
add si,si
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
;Guarda el nuevo valor de basetabla
pop bx
noponnota:
mov al,es:[bx+2]
or al,al
jnz hay_numins
cmp word ptr es:[bx],0
jz noponins
mov al,tab_muest&canal.num_ins
hay_numins:
mov tab_muest&canal.num_ins,al
dec al
mov dl,42
;longitud de un elemento de la tabla de instrumentos
mul dl
add ax,offset tab_ins
xor dl,dl
cmp word ptr es:[bx],0
jne haz_retrig
cmp byte ptr es:[bx+3],0
je haz_retrig
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.45
mov dl,1
haz_retrig:
push bx
mov bx,ax
;bx -> instrumento elegido
mov ax,[bx].volum_ins
mov tab_muest&canal.volumen,ax
;Guarda volumen del instrumento
or dl,dl
jnz noact_ins
mov eax,[bx].base_ins
mov tab_muest&canal.pri_muest,eax
;Guarda offset a la primera pos.
mov ecx,[bx].loop_s
add ecx,eax
mov tab_muest&canal.loopsm,ecx
;Guarda offset del principio del
loop
mov ecx,[bx].long_ins
dec ecx
mov eax,tab_muest&canal.pri_muest
add eax,ecx
mov tab_muest&canal.fin_muest,eax
;Guardar offset del final de la
muestra
mov eax,[bx].loop_l
add eax,tab_muest&canal.loopsm
mov tab_muest&canal.looplm,eax
noact_ins:
pop bx
noponins:
mov ax,es:[bx+3]
;Guarda offset del final del loop
or ax,ax
jnz hayefecto
jmp nada
hayefecto:
cmp al,cod_veloc
;si es el codigo de velocidad
jne no_veloc
cmp ah,32
jb mirar0
jmp nada
mirar0:
;si es >=32, son beats/minuto
or ah,ah
jz nada
jmp pon_tpd
;pon_beat:
mov bl,ah
;
mov ax,750
;
div bl
;
mov ah,al
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
pon_tpd:
Pag. 7.46
mov velocidad,ah
mov cont_tpd,ah
jmp nada
no_veloc:
cmp al,cod_volum
;si es código de volumen
jne novol
mov al,ah
;lee el volumen
xor ah,ah
mov tab_muest&canal.volumen,ax
jmp nada
novol:
cmp al,cod_pitchup
jne noup
mov tab_muest&canal.flag_pitch,1
mov al,ah
xor ah,ah
mov tab_muest&canal.valor_pitch,ax
jmp nada
noup:
cmp al,cod_pitchdo
jne nodwn
mov tab_muest&canal.flag_pitch,1
mov al,ah
xor ah,ah
neg ax
mov tab_muest&canal.valor_pitch,ax
jmp nada
nodwn:
cmp al,cod_vslide
jne noslide
mov tab_muest&canal.flag_slide,1
mov al,ah
test al,0f0h
jz slid_dwn
and al,0f0h
sar al,4
xor ah,ah
mov tab_muest&canal.valor_slide,ax
jmp nada
slid_dwn:
xor ah,ah
neg ax
mov tab_muest&canal.valor_slide,ax
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.47
jmp nada
noslide:
cmp al,cod_arpegio
jne noarpegio
mov tab_muest&canal.flag_arpegio,1
mov cl,ah
mov ax,tab_muest&canal.pitch
sar cl,4
and cl,0fh
jz no_arp1
xor ch,ch
calc_arp1:
mov si,32768
mul si
mov si,34716
div si
loop calc_arp1
no_arp1:
mov tab_muest&canal.arpegio1,ax
mov ax,tab_muest&canal.pitch
mov cl,es:[bx+4]
and cl,0fh
jz no_arp2
xor ch,ch
calc_arp2:
mov si,32768
mul si
mov si,34716
div si
loop calc_arp2
no_arp2:
mov tab_muest&canal.arpegio2,ax
jmp nada
noarpegio:
cmp al,cod_break
; si es el codigo de romper patron
jne noromper
mov hacersalto,1
jmp nada
noromper:
cmp al,cod_salto
jne nosalto
mov al,ah
xor ah,ah
mov cont_pat,ax
mov hacersalto,1
jmp nada
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
nosalto:
Pag. 7.48
cmp al,cod_offset
jne nooffset
xor eax,eax
mov ah,es:[bx+4] ;efecto
add eax,tab_muest&canal.pri_muest
cmp eax,tab_muest&canal.fin_muest
ja nooffset
mov tab_muest&canal.pri_muest,eax
jmp nada
nooffset:
cmp al,cod_tono
jne notslide
mov ax,es:[bx]
or ax,ax
jnz siguetono1
mov ax,tab_muest&canal.finslide
siguetono1:
mov tab_muest&canal.finslide,ax
cmp ax,tab_muest&canal.pitch
jbe es_slideu
mov tab_muest&canal.flag_tslided,1
jmp siguetono3
es_slideu:
mov tab_muest&canal.flag_tslideu,1
siguetono3:
mov al,es:[bx+4]
or al,al
jnz siguetono2
mov al,tab_muest&canal.valefecto
siguetono2:
mov tab_muest&canal.valefecto,al
xor ah,ah
mov tab_muest&canal.valtslide,ax
jmp nada
notslide:
cmp al,cod_special
jne nospecial
mov al,ah
sar al,4
and ax,0f0fh
cmp al,cod_sfvolup
jne nosfvolup
cmp byte ptr tab_muest&canal.volumen,64
je nosfvolup
add byte ptr tab_muest&canal.volumen,ah
jmp nada
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
nosfvolup:
Pag. 7.49
cmp al,cod_sfvoldo
jne nosfvoldo
cmp byte ptr tab_muest&canal.volumen,0
je nosfvoldo
sub byte ptr tab_muest&canal.volumen,ah
jmp nada
nosfvoldo:
nospecial:
nada:
add bx,6
endm
canal4_mono
macro
local buc_canal1,buc_canal2,buc_canal3,buc_canal4
local setloops_c1,setloops_c2,setloops_c3,setloops_c4
local fin_canal1,fin_canal2,fin_canal3,fin_canal4
; Uso de los registros
; ECX
= contador del bucle
; EDX
= proximo valor de la tabla Bresenham
; EBX
= direccion base de la tabla Bresenham
; EBP
= puntero a la muestra a leer
; ES:DI = puntero al buffer DMA
; EAX
= muestra leída
; ESI
= direccion de la tabla de volumenes para cada canal
;Procesando canal 1
movzx ecx,bytes_trans
; Longitud buffer DMA
les di,bloque_lle
; Dirección buffer DMA
movzx edx,br_indice
; Indice al proximo valor de la tabla
de incrementos
mov ebp,tab_muest1.pri_muest
; Dirección de la próxima muestra a
leer
movzx esi,tab_muest1.vol_tabla ; Tabla de traducción para el volúmen
de este canal
movzx ebx,tab_muest1.basetabla ; Dirección base de la tabla de
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.50
incrementos para esta nota
buc_canal1:
xor eax,eax
; Ponemos a 0 todo el registro EAX.
mov al,fs:[ebp]
; AL=muestra actual
mov al,[esi+eax]
; AL=AL*volumen1/128
stosb
; Almacena muestra
mov al,[ebx+edx]
; Lee el valor para incrementar el
puntero a la próxima muestra
inc dl
; Incrementa índice a la tabla de
incrementos
add ebp,eax
; Actualiza puntero a la siguiente
muestra
cmp ebp,tab_muest1.fin_muest
; ¿Se ha terminado de leer la muestra
ja setloops_c1
; Sí, vuelve al principio del loop
loop buc_canal1
; Siguiente muestra
jmp fin_canal1
; Fin de este canal
o el loop?
setloops_c1: mov ebp,tab_muest1.loopsm
; EBP=principio del loop
mov eax,tab_muest1.looplm
mov tab_muest1.fin_muest,eax
; fin_muestra ahora es el fin del
xor eax,eax
; Volvemos a borrar EAX
loop buc_canal1
; Y seguimos leyendo muestras
mov tab_muest1.pri_muest,ebp
; Almacenamos el puntero a la
loop
fin_canal1:
siguiente muestra
;Procesando canal 2 (la mecánica es análoga al canal 1)
movzx ecx,bytes_trans
les di,bloque_lle
mov ebp,tab_muest2.pri_muest
movzx esi,tab_muest2.vol_tabla
movzx ebx,tab_muest2.basetabla
xor eax,eax
buc_canal2:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
add es:[di],al
; En lugar de almacenar la muestra se
añade a la anterior
inc di
; Incrementamos el puntero al buffer
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.51
DMA
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest2.fin_muest
ja setloops_c2
loop buc_canal2
jmp fin_canal2
setloops_c2: mov ebp,tab_muest2.loopsm
mov eax,tab_muest2.looplm
mov tab_muest2.fin_muest,eax
xor eax,eax
loop buc_canal2
fin_canal2:
mov tab_muest2.pri_muest,ebp
;Procesando canal 3
movzx ecx,bytes_trans
les di,bloque_lle
mov ebp,tab_muest3.pri_muest
movzx esi,tab_muest3.vol_tabla
movzx ebx,tab_muest3.basetabla
xor eax,eax
buc_canal3:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
add es:[di],al
inc di
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest3.fin_muest
ja setloops_c3
loop buc_canal3
jmp fin_canal3
setloops_c3: mov ebp,tab_muest3.loopsm
mov eax,tab_muest3.looplm
mov tab_muest3.fin_muest,eax
xor eax,eax
loop buc_canal3
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
fin_canal3:
Pag. 7.52
mov tab_muest3.pri_muest,ebp
;Procesando canal 4
movzx ecx,bytes_trans
les di,bloque_lle
mov ebp,tab_muest4.pri_muest
movzx esi,tab_muest4.vol_tabla
movzx ebx,tab_muest4.basetabla
xor eax,eax
buc_canal4:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
add al,80h
add es:[di],al
inc di
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest4.fin_muest
ja setloops_c4
loop buc_canal4
jmp fin_canal4
setloops_c4: mov ebp,tab_muest4.loopsm
mov eax,tab_muest4.looplm
mov tab_muest4.fin_muest,eax
xor eax,eax
loop buc_canal4
fin_canal4:
mov tab_muest4.pri_muest,ebp
mov br_indice,dx
; Almacenamos índice al próximo valor
de la tabla de incrementos
endm
canal4_st
macro
local buc_canal1,buc_canal2,buc_canal3,buc_canal4
local setloops_c1,setloops_c2,setloops_c3,setloops_c4
local fin_canal1,fin_canal2,fin_canal3,fin_canal4
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.53
; Uso de los registros
; ECX
= contador del bucle
; EDX
= proximo valor de la tabla Bresenham
; EBX
= direccion base de la tabla Bresenham
; EBP
= puntero a la muestra a leer
; ES:DI = puntero al buffer DMA
; EAX
= muestra leída
; ESI
= direccion de la tabla de volumenes para cada canal
;Procesando canal 1
movzx ecx,bytes_trans
shr ecx,1
; La frecuencia de muestreo en
estereo es la mitad que en mono.
les di,bloque_lle
movzx edx,br_indice
mov ebp,tab_muest1.pri_muest
movzx esi,tab_muest1.vol_tabla
movzx ebx,tab_muest1.basetabla
xor eax,eax
buc_canal1:
mov al,fs:[ebp]
mov al,[esi+eax]
stosw
; Almacenamos AL (AH no nos importa)
mov al,[ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest1.fin_muest
ja setloops_c1
loop buc_canal1
jmp fin_canal1
setloops_c1: mov ebp,tab_muest1.loopsm
mov eax,tab_muest1.looplm
mov tab_muest1.fin_muest,eax
xor eax,eax
loop buc_canal1
fin_canal1:
mov tab_muest1.pri_muest,ebp
;Procesando canal 2
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.54
movzx ecx,bytes_trans
shr ecx,1
les di,bloque_lle
inc di
mov ebp,tab_muest2.pri_muest
movzx esi,tab_muest2.vol_tabla
movzx ebx,tab_muest2.basetabla
xor eax,eax
buc_canal2:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
mov es:[di],al
add di,2
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest2.fin_muest
ja setloops_c2
loop buc_canal2
jmp fin_canal2
setloops_c2: mov ebp,tab_muest2.loopsm
mov eax,tab_muest2.looplm
mov tab_muest2.fin_muest,eax
xor eax,eax
loop buc_canal2
fin_canal2:
mov tab_muest2.pri_muest,ebp
;Procesando canal 3
movzx ecx,bytes_trans
shr ecx,1
les di,bloque_lle
inc di
mov ebp,tab_muest3.pri_muest
movzx esi,tab_muest3.vol_tabla
movzx ebx,tab_muest3.basetabla
xor eax,eax
buc_canal3:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.55
add al,80h
add es:[di],al
add di,2
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest3.fin_muest
ja setloops_c3
loop buc_canal3
jmp fin_canal3
setloops_c3: mov ebp,tab_muest3.loopsm
mov eax,tab_muest3.looplm
mov tab_muest3.fin_muest,eax
xor eax,eax
loop buc_canal3
fin_canal3:
mov tab_muest3.pri_muest,ebp
;Procesando canal 4
movzx ecx,bytes_trans
shr ecx,1
les di,bloque_lle
mov ebp,tab_muest4.pri_muest
movzx esi,tab_muest4.vol_tabla
movzx ebx,tab_muest4.basetabla
xor eax,eax
buc_canal4:
mov al,byte ptr fs:[ebp]
mov al,[esi+eax]
add al,80h
add es:[di],al
add di,2
mov al,byte ptr [ebx+edx]
inc dl
add ebp,eax
cmp ebp,tab_muest4.fin_muest
ja setloops_c4
loop buc_canal4
jmp fin_canal4
setloops_c4: mov ebp,tab_muest4.loopsm
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.56
mov eax,tab_muest4.looplm
mov tab_muest4.fin_muest,eax
xor eax,eax
loop buc_canal4
fin_canal4:
mov tab_muest4.pri_muest,ebp
mov br_indice,dx
endm
efectos
macro canal
local nopitch,noslide,noarpegio,notslide,nofin_u,nofin_d
local final,mayor113,menor856,menor64,mayor0,notslideu
local notslided
cmp tab_muest&canal.flag_pitch,0
jz nopitch
mov ax,tab_muest&canal.pitch
sub ax,tab_muest&canal.valor_pitch
cmp ax,113
jge mayor113
mov ax,tab_muest&canal.pitch
mayor113:
cmp ax,856
jle menor856
mov ax,tab_muest&canal.pitch
menor856:
mov si,ax
mov tab_muest&canal.pitch,ax
add si,si
mov bx,offset frec2offs
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
jmp final
nopitch:
cmp tab_muest&canal.flag_slide,0
jz noslide
mov ax,tab_muest&canal.volumen
add ax,tab_muest&canal.valor_slide
cmp ax,64
jle menor64
mov ax,64
menor64:
cmp ax,0
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.57
jge mayor0
xor ax,ax
mayor0:
mov tab_muest&canal.volumen,ax
mul byte ptr volumen&canal
shr ax,6
mov tab_muest&canal.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest&canal.vol_tabla,ax
jmp final
noslide:
cmp tab_muest&canal.flag_arpegio,0
jz noarpegio
mov ax,tab_muest&canal.pitch
mov si,tab_muest&canal.arpegio1
mov tab_muest&canal.pitch,si
mov bx,tab_muest&canal.arpegio2
mov tab_muest&canal.arpegio1,bx
mov tab_muest&canal.arpegio2,ax
add si,si
mov bx,offset frec2offs
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
jmp final
noarpegio:
cmp tab_muest&canal.flag_tslideu,0
jz notslideu
mov si,tab_muest&canal.pitch
sub si,tab_muest&canal.valtslide
cmp si,tab_muest&canal.finslide
ja nofin_u
mov si,tab_muest&canal.finslide
mov tab_muest&canal.flag_tslideu,0
nofin_u:
mov tab_muest&canal.pitch,si
add si,si
mov bx,offset frec2offs
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
jmp final
notslideu:
cmp tab_muest&canal.flag_tslided,0
jz notslided
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.58
mov si,tab_muest&canal.pitch
add si,tab_muest&canal.valtslide
cmp si,tab_muest&canal.finslide
jb nofin_d
mov si,tab_muest&canal.finslide
mov tab_muest&canal.flag_tslided,0
nofin_d:
mov tab_muest&canal.pitch,si
add si,si
mov bx,offset frec2offs
mov ax,[bx+si-226]
mov tab_muest&canal.basetabla,ax
jmp final
notslided:
final:
endm
init_sb
proc near
push ds
espera_esc
mov al,0d1h
out dx,al
espera_esc
mov al,40h
out dx,al
espera_esc
mov al,sb_time
out dx,al
mov ah,35h
mov al,sb_int
int 21h
mov offdsp,bx
mov segdsp,es
mov ah,25h
mov al,sb_int
mov dx,offset int_dma
mov bx,seg int_dma
mov ds,bx
int 21h
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.59
pop ds
mov al,sb_int
sub al,8
mov cl,al
mov al,1
sal al,cl
mov bl,al
not bl
in al,21h
and al,bl
out 21h,al
mov dx,sb_puerto
sub dx,8
mov al,0eh
out dx,al
inc dx
in al,dx
and al,0FDh
out dx,al
cmp disp_salida,SBP_ST
jne no_act_ste
mov dx,sb_puerto
sub dx,8
mov al,0eh
out dx,al
inc dx
in al,dx
or al,2h
out dx,al
no_act_ste:
ret
init_sb
endp
deinit_sb
proc near
mov dx,sb_puerto
sub dx,0ch
call reset_dsp
push ds
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.60
mov ah,25h
mov al,sb_int
lds dx,dword ptr offdsp
int 21h
pop ds
cmp disp_salida,SBP_ST
jne no_de_ste
mov dx,sb_puerto
sub dx,8
mov al,0eh
out dx,al
inc dx
in al,dx
and al,0FDh
out dx,al
no_de_ste:
ret
deinit_sb
endp
init_dac
proc near
mov ax,3508h
int 21h
mov word ptr ant08,bx
mov word ptr ant08+2,es
push ds
mov dx,offset int08dac
mov ax,seg int08dac
mov ds,ax
mov ax,2508h
int 21h
pop ds
mov al,periodo
out 40h,al
jmp $+2
mov al,0
out 40h,al
mov ax,lptdata
; Parcheamos la dirección para
mov word ptr cs:[parche+1],ax ; mayor velocidad de ejecución
ret
init_dac
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
deinit_dac
Pag. 7.61
proc near
push ds
lds dx,ant08
mov ax,2508h
int 21h
pop ds
xor al,al
out 40h,al
jmp $+2
out 40h,al
ret
deinit_dac
endp
init_proy
proc near
mov ah,35h
mov al,numintp
int 21h
mov word ptr antproy,bx
mov word ptr antproy+2,es
cli
push ds
mov al,numintp
mov dx,offset intproy
mov bx,seg intproy
mov ds,bx
mov ah,25h
int 21h
pop ds
in al,21h
and al,01011111b
out 21h,al
mov dx,lptctrl
mov al,10h
out dx,al
push 0036h
; Programar timer 0, modo 3
push 0001h
; Los tres argumentos de la llamada a e8253
push 0001h
call e8253
add sp,6
mov al,perproy
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.62
xor ah,ah
push ax
push 0000h
push 0000h
call e8253
add sp,6
push 0000h
push 0000h
push 0000h
call e8253
add sp,6
sti
ret
init_proy
endp
deinit_proy
proc near
mov dx,lptctrl
mov al,03h
out dx,al
mov al,numintp
push ds
lds dx,antproy
mov ah,25h
int 21h
pop ds
ret
deinit_proy
endp
init_spk
proc near
mov ax,3508h
int 21h
mov word ptr ant08,bx
mov word ptr ant08+2,es
push ds
mov dx,offset int08spk
mov ax,seg int08spk
mov ds,ax
mov ax,2508h
int 21h
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.63
pop ds
mov al,periodo
out 40h,al
jmp $+2
mov al,0
out 40h,al
in al,97
or al,3
out 97,al
mov al,10010000b
out 43h,al
ret
init_spk
endp
deinit_spk
proc near
push ds
lds dx,ant08
mov ax,2508h
int 21h
pop ds
xor al,al
out 40h,al
jmp $+2
out 40h,al
in al,97
and al,0fch
out 97,al
ret
deinit_spk
endp
init_sampler proc C
cli
cmp disp_salida,ALTAVOZ
jne no_altavoz
call init_spk
jmp sigue_init
no_altavoz:
cmp disp_salida,DAC_LPT
jne no_dac
call init_dac
jmp sigue_init
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
no_dac:
Pag. 7.64
cmp disp_salida,PROY
jne no_proy
call init_proy
jmp sigue_init
no_proy:
call init_sb
;INICIALIZAR TABLAS Y VARIABLES
sigue_init:
mov terminado,0
mov fin_canc,0
mov hacersalto,0
mov br_indice,0
mov conta_frames,0
mov indice_int,0
mov ax,bytes_trans
mov cont_int,ax
mov ax,periodo_ant08
mov cont_ant08,ax
mov al,velocidad
mov cont_tpd,al
mov bx,offset lis_patt
mov si,cont_pat
inc cont_pat
mov al,[bx+si]
mov bl,4
;leer el nº de patron que sigue en la lista
;tamaño de un elemento de la tabla de punteros a patrones
mul bl
mov bx,ax
add bx,offset tab_patt ;bx -> puntero a la direccion del patron a
;tocar
mov dx,[bx]
;dx=offset del nuevo patron
mov al,24
;longitud en bytes de una linea
mul cont_lin
add dx,ax
mov linea_act,dx
mov dx,[bx+2]
;dx=segmento del nuevo patron
mov patr_act,dx
push es
mov es,dx
;es direcciona el nuevo patron
mov bx,linea_act
;bx se va moviendo a traves del patron
call actual_canal
mov linea_act,bx
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.65
pop es
call ponvolumen
call llenar_dma
call swap_bloque
call llenar_dma
cmp disp_salida,SB20
jb fin_init
call setup_dma
fin_init:
sti
ret
init_sampler endp
des_sampler
proc C
cli
cmp disp_salida,ALTAVOZ
jne no_dalta
call deinit_spk
jmp sigue_des
no_dalta:
cmp disp_salida,DAC_LPT
jne no_ddac
call deinit_dac
jmp sigue_des
no_ddac:
cmp disp_salida,PROY
jne no_dproy
call deinit_proy
jmp sigue_des
no_dproy:
call deinit_sb
sigue_des:
sti
ret
des_sampler
endp
int_dma
proc far
push eax
push ebx
push ecx
push edx
push esi
push edi
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.66
push ebp
push ds
push es
push fs
cld
mov ax,dgroup
mov ds,ax
xor ax,ax
mov fs,ax
mov dx,sb_puerto
add dx,2
in al,dx
;ACK al DSP. Interrupción recibida.
mov al,20h
out 20h,al ;ACK al 8259.
inc conta_frames
cmp terminado,1
je fin_intsb
cmp fin_canc,1
je fin_total
call swap_bloque
call setup_dma
call llenar_dma
call calc_efecto
jmp fin_intsb
fin_total:
mov terminado,1
fin_intsb:
pop fs
pop es
pop ds
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
iret
int_dma
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
int08dac
Pag. 7.67
proc far
push ax
push bx
push dx
push si
push ds
push es
mov al,20h
out 20h,al
mov ax,dgroup
mov ds,ax
cmp terminado,0
jne fin_idac
les si,bloque_dma
parche:
mov dx,378h
mov bx,indice_int
mov al,es:[bx+si]
out dx,al
inc indice_int
dec cont_int
jz fin_bl_dac
fin_idac:
dec cont_ant08
jz llama_reld
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
fin_bl_dac:
call prep_datos
dec cont_ant08
jz llama_reld
pop es
pop ds
pop si
pop dx
pop bx
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.68
pop ax
iret
llama_reld:
pushf
call dword ptr ant08
mov ax,periodo_ant08
mov cont_ant08,ax
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
int08dac
endp
int08spk
proc far
push ax
push bx
push dx
push si
push ds
push es
mov al,20h
out 20h,al
mov ax,dgroup
mov ds,ax
cmp terminado,0
jne fin_ispk
les si,bloque_dma
mov bx,indice_int
mov al,es:[bx+si]
mov bx,offset compresion
xlat
mul periodo
mov al,ah
out 42h,al
inc indice_int
dec cont_int
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.69
jz fin_bl_spk
fin_ispk:
dec cont_ant08
jz llama_rels
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
fin_bl_spk:
call prep_datos
dec cont_ant08
jz llama_rels
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
llama_rels:
pushf
call dword ptr ant08
mov ax,periodo_ant08
mov cont_ant08,ax
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
int08spk
endp
intproy
proc far
push ax
push bx
push dx
push si
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.70
push ds
push es
mov al,20h
out 20h,al
mov ax,dgroup
mov ds,ax
cmp terminado,0
jne fin_iproy
les si,bloque_dma
mov bx,indice_int
mov al,es:[bx+si]
mov dx,lptdata
out dx,al
mov al,00010010b
mov dx,lptctrl
out dx,al
jmp $+2
mov al,00010011b
out dx,al
jmp $+2
mov al,es:[bx+si+1]
mov dx,lptdata
out dx,al
jmp $+2
mov al,00010001b
mov dx,lptctrl
out dx,al
jmp $+2
mov al,00010011b
out dx,al
add indice_int,2
sub cont_int,2
jz fin_bl_pry
fin_iproy:
pop es
pop ds
pop si
pop dx
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.71
pop bx
pop ax
iret
fin_bl_pry:
call prep_datos
pop es
pop ds
pop si
pop dx
pop bx
pop ax
iret
intproy
endp
prep_datos
proc near
push eax
push ebx
push ecx
push edx
push esi
push edi
push ebp
push fs
cld
inc conta_frames
cmp terminado,0
jne fin_prep
cmp fin_canc,0
jne fin_tprep
mov ax,bytes_trans
mov cont_int,ax
mov indice_int,0
call swap_bloque
xor ax,ax
mov fs,ax
sti
call llenar_dma
call calc_efecto
cli
jmp fin_prep
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
fin_tprep:
mov terminado,1
fin_prep:
pop fs
Pag. 7.72
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
ret
prep_datos
endp
actualiza
proc near
actualiz:
mov chivato,1
cmp hazpausa,1
jne nopausa
ret
nopausa:
cmp hacersalto,1
jne nohazsalto
mov hacersalto,0
jmp cambpat
nohazsalto:
inc cont_lin
cmp cont_lin,64
jne nocambpat
jmp cambpat
nocambpat:
mov ax,patr_act
mov es,ax
;es direcciona el nuevo patron
mov bx,linea_act
;bx se va moviendo a traves del patron
call actual_canal
mov linea_act,bx
call ponvolumen
ret
cambpat:
mov cont_lin,255
mov bx,offset lis_patt
mov si,cont_pat
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.73
inc cont_pat
mov al,[bx+si]
;leer el nº de patron que sigue en la lista
cmp al,128
je fintocar
mov bl,4
;tamaño de un elemento de la tabla de punteros a patrones
mul bl
mov bx,ax
add bx,offset tab_patt ;bx -> puntero al patron a tocar
mov dx,[bx]
;dx=offset del nuevo patron
mov linea_act,dx
mov dx,[bx+2]
;dx=segmento del nuevo patron
mov patr_act,dx
jmp actualiz
fintocar:
mov fin_canc,1
ret
actualiza
endp
actual_canal proc near
act_canal 1
act_canal 2
act_canal 3
act_canal 4
ret
actual_canal endp
calc_efecto
proc near
efectos 1
efectos 2
efectos 3
efectos 4
dec cont_tpd
jnz no_llam_act
mov al,velocidad
mov cont_tpd,al
jmp actualiza
no_llam_act: ret
calc_efecto
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
ponvolumen
Pag. 7.74
proc C
mov al,byte ptr tab_muest1.volumen
mul volumen1
shr ax,6
mov tab_muest1.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest1.vol_tabla,ax
mov al,byte ptr tab_muest2.volumen
mul volumen2
shr ax,6
mov tab_muest2.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest2.vol_tabla,ax
mov al,byte ptr tab_muest3.volumen
mul volumen3
shr ax,6
mov tab_muest3.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest3.vol_tabla,ax
mov al,byte ptr tab_muest4.volumen
mul volumen4
shr ax,6
mov tab_muest4.vol_play,ax
shl ax,8
add ax,offset tabla_g_vol
mov tab_muest4.vol_tabla,ax
ret
ponvolumen
endp
reset_dsp
proc far
push dx
add dx,6
mov al,1
out dx,al
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.75
mov cx,1000
simul_hlt:
nop
loop simul_hlt
xor al,al
out dx,al
add dx,4
mov cx,800
buc_pool:
in al,dx
cmp al,0aah
je hay_dsp
loop buc_pool
pop dx
mov ax,1
ret
hay_dsp:
pop dx
add dx,0ch
mov sb_puerto,dx
mov al,0d1h
out dx,al
;
sub dx,8
;
mov al,4
;
out dx,al
;
inc dx
;
mov al,0ffh
;
out dx,al
;
dec dx
;
mov al,22h
;
out dx,al
;
inc dx
;
mov al,0ffh
;
out dx,al
mov ax,0
ret
reset_dsp
endp
detecta_SB
proc C
mov dx,210h
call reset_dsp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.76
jne sigue_1
mov al,'3'
jmp fin_sb
sigue_1:
mov dx,220h
call reset_dsp
jne sigue_2
mov al,'5'
jmp fin_sb
sigue_2:
mov dx,230h
call reset_dsp
jne sigue_3
mov al,'3'
jmp fin_sb
sigue_3:
mov dx,240h
call reset_dsp
jne sigue_4
mov al,'5'
jmp fin_sb
sigue_4:
mov dx,250h
call reset_dsp
jne sigue_5
mov al,'3'
jmp fin_sb
sigue_5:
mov dx,260h
call reset_dsp
jne sigue_6
mov al,'3'
jmp fin_sb
sigue_6:
mov al,'2'
fin_sb:
mov ah,0
ret
detecta_SB
endp
detecta_LPT
proc C num_lpt:word
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.77
push es
push si
mov ax,40h
mov es,ax
mov si,num_lpt
add si,si
add si,8
mov ax,es:[si]
mov lptdata,ax
inc ax
mov lptstd,ax
inc ax
mov lptctrl,ax
pop si
pop es
dec ax
dec ax
ret
detecta_LPT
endp
e8253
proc C a1:byte, a0:byte, valor:byte
mov dx,lptdata
mov al,valor
out dx,al
mov dx,lptctrl
in al,dx
mov cl,al
mov al,a0
sal al,2
mov bl,a1
xor bl,1
sal bl,1
or al,bl
or al,19h
out dx,al
jmp $+2
and al,0feh
out dx,al
jmp $+2
mov al,cl
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.78
out dx,al
ret
e8253
endp
swap_bloque
proc near
mov eax,bloque_dma
xchg eax,bloque_lle
mov bloque_dma,eax
ret
swap_bloque
endp
setup_dma
proc near
;SETUP del DMA
mov al,sb_dma
or al,100b
out 0ah,al
; Poner máscara a DMA
out 0ch,al
; borrar flip-flop con cualquier dato
mov al,48h
or al,sb_dma
out 0bh,al
; Hacer DMA -> DAC
mov ax,word ptr bloque_dma+2
mov bx,16
mul bx
; DX:AX=SEG(bloque_dma)<<4
add ax,word ptr bloque_dma
adc dx,0
; DX:AX=dirección lineal del buffer
mov bl,dl
; BL=página del bloque DMA
DMA
xor dh,dh
mov dl,sb_dma
inc dx
out dx,al
; Almacenamos la dirección
mov al,ah
; base (16 bits bajos) del
out dx,al
; bloque DMA
inc dx
mov ax,bytes_trans
dec ax
out dx,al
; Y ahora almacenamos la
mov al,ah
; longitud del bloque DMA
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
out dx,al
Pag. 7.79
; (hasta 64K)
mov al,bl
cmp sb_dma,0
; Miramos en qué canal está la SB
jne canal_1
; para almacenar el valor de la
out 87h,al
; en el registro adecuado
página
jmp f_setup_dma
canal_1:
cmp sb_dma,1
jne canal_3
out 83h,al
jmp f_setup_dma
canal_3:
out 82h,al
f_setup_dma: mov al,sb_dma
out 0ah,al
; Comando: transferencia memoria->E/S
bajo demanda
;SETUP del DSP
espera_esc
mov al,48h
out dx,al
mov cx,bytes_trans
dec cx
espera_esc
mov al,cl
out dx,al
espera_esc
mov al,ch
out dx,al
espera_esc
mov al,91h
;Comando: DAC por DMA, high-speed
out dx,al
ret
setup_dma
endp
llenar_mono
proc near
push ebp
canal4_mono
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.80
pop ebp
ret
llenar_mono
endp
llenar_ste
proc near
push ebp
canal4_st
pop ebp
ret
llenar_ste
endp
llenar_dma
proc near
cmp disp_salida,SBP_ST
je es_ste
cmp disp_salida,PROY
je es_ste
jmp llenar_mono
es_ste:
jmp llenar_ste
llenar_dma
endp
end
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.81
SECUENC.INC
comment %
----------------------------------------------------------------------------LISTAS GENERADAS POR EL ALGORITMO DE BRESENHAM PARA CAMBIAR EL PITCH DE CADA
MUESTRA DE ACUERDO CON LA NOTA Y LA OCTAVA QUE SE QUIERE TOCAR.
----------------------------------------------------------------------------%
sec_do0
db 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0
db 0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0
db 0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0
db 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
db 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0
db 0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0
db 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0
db 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
db 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
sec_dos0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1
db 0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1
db 0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1
db 0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1
db 0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1
db 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0
sec_re0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0
db 0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0
db 0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0
db 0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0
db 0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0
db 0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0
db 0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1
db 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0
sec_res0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0
db 0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0
db 0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0
db 0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.82
db 0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0
db 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0
sec_mi0
db 1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0
db 0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0
db 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0
db 0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0
db 1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0
db 0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0
db 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0
db 0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1
db 0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0
sec_fa0
db 1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0
db 1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1
db 0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1
db 0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0
db 0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0
db 0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0
db 0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0
db 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0
db 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0
sec_fas0
db 1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0
db 0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0
db 0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0
db 1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0
db 0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0
db 0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1
db 0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0
db 0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0
db 0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0
sec_sol0
db 1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0
db 0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1
db 0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
db 0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0
db 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1
db 0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0
db 0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0
db 0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0
db 1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0
sec_sols0
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.83
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
db 0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0
db 0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0
sec_la0
db 1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0
db 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0
db 0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1
db 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0
db 0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0
db 1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,1
db 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0
db 0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0
sec_las0
db 1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0
db 0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0
db 0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0
db 1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0
db 0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0
db 0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1
db 0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0
db 0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0
db 0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0
sec_si0
db 1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1
db 0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1
db 0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0
db 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0
db 0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0
db 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0
db 0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0
db 0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0
db 1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0
sec_do1
db 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0
db 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0
db 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0
db 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0
db 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0
db 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0
db 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0
db 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0
db 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0
sec_dos1
db 1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.84
db 1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0
db 1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0
db 1,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1
db 0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1
db 0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1
db 0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1
db 0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1
db 0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0
sec_re1
db 1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0
db 0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0
db 0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0
db 0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0
db 0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,1
db 0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0
sec_res1
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0
sec_mi1
db 1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0
db 0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0
db 1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0
db 0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0
db 1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0
db 0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1
db 0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0
db 0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1
db 0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,1
sec_fa1
db 1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0
db 1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1
db 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1
db 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0
db 0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0
db 0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0
db 0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.85
db 1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0
db 1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1
sec_fas1
db 1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0
db 0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1
db 0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0
db 1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0
db 1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0
db 0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1
db 0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0
db 1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0
db 0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1
sec_sol1
db 1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1
db 0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1
db 0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0
db 0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0
db 1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1
db 0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1
db 0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0
db 0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0
db 1,0,0,1,0,1,0,0,1,0,0,1,0,1,0,0
sec_sols1
db 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0
db 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0
db 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0
db 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0
db 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0
db 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0
db 1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0
db 0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0
db 0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,0
sec_la1
db 1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0
db 0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1
db 0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0
db 1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1
db 0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1
db 0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0
db 1,0,0,1,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1
db 0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0,1,0,0
db 1,0,1,0,1,0,0,1,0,1,0,1,0,0,1,0
sec_las1
db 1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1
db 0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0
db 1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0
db 1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,1
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.86
db 0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0
db 1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1
db 0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0
db 0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,0
db 1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1
sec_si1
db 1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1
db 0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1
db 0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0
db 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0
db 1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0
db 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1
db 0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1
db 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0
db 1,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1
sec_do2
db 128 dup (1,0)
sec_dos2
db 1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0
db 1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0
db 1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0
db 1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1
db 0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1
db 0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1
db 0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1
db 0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1
db 0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0
sec_re2
db 1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0
db 1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0
db 1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0
db 1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0
db 1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0
db 1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0
db 1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1
db 0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1,0,1,0,1,1
db 0,1,0,1,0,1,1,0,1,0,1,0,1,1,0,1
sec_res2
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1,0,1,1,0
db 1,0,1,1,0,1,0,1,1,0,1,0,1,1,0,1
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
sec_mi2
Pag. 7.87
db 1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0
db 1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0
db 1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0
db 1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0
db 1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1
db 0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1
db 0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1
db 0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1
db 0,1,1,0,1,1,0,1,0,1,1,0,1,1,0,1
sec_fa2
db 1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0
db 1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1
db 0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1
db 1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,0
db 1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1
db 0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1
db 0,1,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1
db 1,0,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0
db 1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1
sec_fas2
db 1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1
db 0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1
db 1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0
db 1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1
db 1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0
db 1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1
db 0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1
db 1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1
db 0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1
sec_sol2
db 1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1
db 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1
db 1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1
db 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1
db 1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1
db 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1
db 1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1
db 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1
db 1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1
sec_sols2
db 1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1
db 1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1
db 1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1
db 1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1
db 1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1
db 1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.88
db 1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1
db 0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1
db 0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0
sec_la2
db 1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0
db 1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1
db 1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1
db 1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1
db 1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1
db 0,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1
db 1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0,1,1
db 1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,0
db 1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1
sec_las2
db 1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1
db 1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1
db 1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0
db 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1
db 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1
db 1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1
db 1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1
db 0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1
db 1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1
sec_si2
db 1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1
sec_do3
db 256 dup(1)
sec_dos3
db 2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1
db 1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1
db 1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1
db 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1
db 1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1
db 1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1
db 1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1
db 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1
sec_re3
db 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1
db 1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.89
db 1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1
db 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1
db 1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1
db 1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1
db 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1
db 1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1
db 1,1,1,1,1,2,1,1,1,1,1,1,1,2,1,1
sec_res3
db 2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1
db 1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1
db 1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1
db 2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1
db 1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1
db 1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1
db 2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1
db 1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1
db 1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1
sec_mi3
db 2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1
db 1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1
db 1,1,2,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,1
db 1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2
db 1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,1
db 2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1
db 1,2,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1
db 1,1,2,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2
db 1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,1
sec_fa3
db 2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1
db 2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1
db 2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1
db 2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,2,1,1,2,1,1,2
db 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2
db 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2
db 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2
db 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1,1,2
db 1,1,2,1,1,2,1,1,2,1,1,2,1,1,2,1
sec_fas3
db 2,1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,1,2,1,2
db 1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1
db 2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2
db 1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1
db 1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1
db 2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2
db 1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1
db 2,1,2,1,1,2,1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1,2,1,2,1,1,2,1,2
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.90
db 1,2,1,1,2,1,2,1,1,2,1,2,1,2,1,1
sec_sol3
db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1
db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1
db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1
db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1
db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,1,2
db 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
db 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
db 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
db 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2
sec_sols3
db 2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,1,2,2,1,2
db 1,2,2,1,2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,1
db 2,2,1,2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,1,2
db 2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,2,1,2
db 1,2,1,2,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2,1,2,1
db 2,1,2,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2
db 2,1,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2
db 1,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2,1
db 2,1,2,2,1,2,1,2,1,2,2,1,2,1,2,2
sec_la3
db 2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,2,1,2,2,1,2,2
db 1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2
db 2,1,2,2,1,2,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,2
db 1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,2,1,2,2,1,2,2,1,2
db 2,1,2,2,1,2,2,1,2,2,1,2,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1
db 2,2,1,2,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,2,1,2
db 2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,2,1,2,2,1,2,2,1,2,2,1
db 2,2,1,2,2,1,2,2,1,2,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2
db 1,2,2,2,1,2,2,1,2,2,1,2,2,1,2,2
sec_las3
db 2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2
db 1,2,2,2,1,2,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2
db 2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,1
db 2,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2
db 2,1,2,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1
db 2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2
db 2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,2,1
db 2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2,1,2,2,2,2,1,2,2,2
db 2,1,2,2,2,1,2,2,2,2,1,2,2,2,1,2
sec_si3
db 2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2
db 2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2
db 2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2
db 2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2
db 1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.91
db 2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2
db 2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1
db 2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2,2,2
db 2,2,2,2,2,1,2,2,2,2,2,2,2,2,1,2
sec_do4
db 256 dup(2)
sec_dos4
db 3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2
db 2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,3
db 2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2
db 2,2,3,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,3,2
db 2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2
db 2,3,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,3,2,2
db 2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2
db 3,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2,2
db 2,2,2,2,3,2,2,2,2,2,2,2,3,2,2,2
sec_re4
db 3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,2,3
db 2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2
db 2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2
db 3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2
db 2,2,3,2,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2
db 2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,2,3,2,2,2
db 3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2
db 2,2,3,2,2,2,3,2,2,2,3,2,2,2,2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2
db 2,3,2,2,2,3,2,2,2,3,2,2,2,3,2,2
sec_res4
db 3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3
db 2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,3,2,2,3,2
db 2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2
db 3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3
db 2,2,3,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2
db 2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2
db 3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,3,2,2,3,2,2,3
db 2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2,3,2,2,3,2
db 3,2,2,3,2,2,3,2,3,2,2,3,2,2,3,2
sec_mi4
db 3,2,3,2,3,2,3,2,3,2,3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3
db 2,3,2,3,2,3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2
db 3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,3,2
db 3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,3,2,3,2,3,2,3
db 2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,3,2,3,2,3,2,3,2,3,2
db 3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3
db 2,3,2,3,2,3,2,3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2
db 3,2,3,2,3,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2,3
db 3,2,3,2,3,2,3,2,3,2,3,2,3,2,3,2
sec_fa4
db 3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.92
db 3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2
db 3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2
db 3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,3,2,3,3,2,3,3
db 2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3
db 2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3
db 2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3
db 2,3,3,2,3,3,2,3,3,2,3,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3,2,3
db 3,2,3,3,2,3,3,2,3,3,2,3,3,2,3,3
sec_fas4
db 3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,3,2,3,3,3
db 3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3
db 3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3
db 2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,2
db 3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2
db 3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3
db 3,3,3,3,2,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3
db 3,3,3,2,3,3,3,3,3,2,3,3,3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3,3,3
db 3,3,2,3,3,3,3,3,2,3,3,3,3,3,2,3
sec_sol4
db 4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2
db 4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2
db 4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2
db 4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2
db 4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,2,4
db 2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4
db 2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4
db 2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4
db 2,4,2,4,2,4,2,4,2,4,2,4,2,4,2,4
sec_sols4
db 4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,2,4,4,2,4
db 2,4,4,2,4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,2
db 4,4,2,4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,2,4
db 4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,4,2,4
db 2,4,2,4,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4,2,4,2
db 4,2,4,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4
db 4,2,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4
db 2,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4,2
db 4,2,4,4,2,4,2,4,2,4,4,2,4,2,4,4
sec_la4
db 4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,4,2,4,4,2,4,4
db 2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4
db 4,2,4,4,2,4,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,4
db 2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,4,2,4,4,2,4,4,2,4
db 4,2,4,4,2,4,4,2,4,4,2,4,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2
db 4,4,2,4,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,4,2,4
db 4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,4,2,4,4,2,4,4,2,4,4,2
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.93
db 4,4,2,4,4,2,4,4,2,4,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4,2,4,4
db 2,4,4,4,2,4,4,2,4,4,2,4,4,2,4,4
sec_las4
db 4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4
db 2,4,4,4,2,4,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4
db 4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,2
db 4,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4
db 4,2,4,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2
db 4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4
db 4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,4,2
db 4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4,2,4,4,4,4,2,4,4,4
db 4,2,4,4,4,2,4,4,4,4,2,4,4,4,2,4
sec_si4
db 4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4
db 4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4
db 4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4
db 4,4,4,4,2,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4
db 2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4
db 4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4
db 4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2
db 4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4,4,4
db 4,4,4,4,4,2,4,4,4,4,4,4,4,4,2,4
tabla_bres
dw offset sec_dos0
public C tabla_bres
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.94
COMPRES.INC
compresion
db 1,1,1,1,1,2,2,3,3,3,4,4,4,5,5,5
db 6,6,7,7,7,8,8,8,9,9,9,10,10,11,11,11
db 12,12,12,13,13,13,14,14,15,15,15,16,16,16,17,17
db 18,18,18,19,19,19,20,20,20,21,21,22,22,22,23,23
db 23,24,24,24,25,25,26,26,26,27,27,27,28,28,28,29
db 29,30,30,30,31,31,33,36,38,40,42,45,47,49,51,54
db 56,58,60,63,65,67,69,72,74,76,78,81,83,85,87,90
db 92,94,97,99,101,103,106,108,110,112,115,117,119,121,124,126
db 128,130,133,135,137,139,142,144,146,148,151,153,155,157,160,162
db 164,167,169,171,173,176,178,180,182,185,187,189,191,194,196,198
db 200,203,205,207,209,212,214,216,218,221,223,223,224,224,225,225
db 225,226,226,226,227,227,228,228,228,229,229,229,230,230,231,231
db 231,232,232,232,233,233,234,234,234,235,235,235,236,236,237,237
db 237,238,238,238,239,239,240,240,240,241,241,241,242,242,243,243
db 243,244,244,244,245,245,246,246,246,247,247,247,248,248,249,249
db 249,250,250,250,251,251,252,252,252,253,253,253,254,254,255,255
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.95
TRPLAY.C
#include <stdio.h>
#include <string.h>
#include <process.h>
#include <stdlib.h>
#include "tracklib.h"
#include "xmem.h"
// Modelo large
#define QUIET(p) if (!silenc) p;
#define PRDISP
QUIET (printf ("Reproduciendo %s
Hz\n",fmodulo,nombremod,frecuencia))
\
QUIET (printf ("ESC:salir
S:shell al DOS\n"))
%s\nFrecuencia de muestreo: %u
Espacio:pausa/sigue ejecución
\
QUIET (printf ("Dispositivo de reproducción: "))
switch (disp_salida)
{
\
\
\
case ALTAVOZ: QUIET (printf ("Altavoz interno.\n\n"))
break;
\
case DAC_LPT: QUIET (printf ("DAC en puerto LPT:
%04.4X\n\n",lptdata)) break;
\
case PROY:
QUIET (printf ("Tarjeta de sonido de
proyecto en puerto LPT: %04.4X\n\n",lptdata)) break;
default:
\
QUIET (printf ("Sound Blaster %s en puerto:
%04.4X, IRQ:%d, DMA:%d\n\n",(disp_salida==SBP_MONO)? "mono":"Pro",
sb_puerto-12,sb_int-8,sb_dma))
\
}
void main(int argc,char *argv[])
{
int estado;
// Resultado de la carga del módulo
FILE *modulo;
// Fichero .MOD
char tecla,letra,i;
char opcion[80],fmodulo[80];
char silenc=0;
char exe=0;
char num_lpt;
char ejecut[80];
unsigned memoria_total;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.96
char modo;
if (argc==1)
{
printf ("TRPLAY 2.1
Reproductor de módulos de Amiga para PC\n");
printf ("Sintaxis:\n");
printf ("TRPLAY modulo[.MOD] [-{SPK | DACx | SBP_MONO | SBP_ST | PROY}]
[-QUIET]\n");
printf ("[-EXEprograma] [-MEMtamaño] [-{NTSC | PAL}] [-{A|B|C...|X}]\n\n");
printf ("
SPK
: Reproduce a través del altavoz interno.\n");
printf ("
DACx
: Usa un DAC en el puerto LPTx.\n");
printf ("
SBP_MONO : Usa una Sound Blaster 2.0 o SB Pro monoaural.\n");
printf ("
SBP_ST
: Usa una Sound Blaster Pro en estéreo.\n");
printf ("
PROY
: Usa la tarjeta de sonido del proyecto.\n");
printf ("
QUIET
: Modo silencioso. No se escribe nada en
EXE
: Ejecuta el programa especificado sin interrumpir la
MEM
: Reserva 'tamaño' Kbytes de XMS para
pantalla.\n");
printf ("
música.\n");
printf ("
instrumentos.\n");
printf ("
NTSC/PAL : Selecciona temporización. Necesario para algunos
MOD's.\n");
printf ("
A - X
: Frec. de muestreo.
A = 31388 Hz
X =
8313
Hz\n\n");
printf ("Por defecto se asume 1Mb XMS, SOund Blaster Pro y 22195 Hz (G)\n");
printf ("o el altavoz interno si no hay tarjeta Sound Blaster.\n\n");
printf ("(c) 1992-1995 Miguel Angel Rodriguez Jodar.\n");
printf ("Este programa es freeware.\n");
printf ("Para cualquier duda o comentario e-mail a:\n");
printf ("
[email protected] or [email protected]\n");
exit(0);
}
letra='G';
disp_salida=NULO;
num_lpt=1;
memoria_total=1024;
modo=PAL;
strcpy(fmodulo,argv[1]);
strupr(fmodulo);
if (!strstr(fmodulo,".MOD"))
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.97
strcat(fmodulo,".MOD");
for (i=2;i<argc;i++)
{
strcpy (opcion,argv[i]);
strupr (opcion);
if (strlen(opcion)==2 && opcion[0]=='-' && opcion[1]>='A' &&
opcion[1]<='X')
letra=opcion[1];
else if (opcion[0]=='-' && !strcmp(opcion+1,"SPK"))
disp_salida=ALTAVOZ;
else if (opcion[0]=='-' && !strncmp(opcion+1,"DAC",3))
{
disp_salida=DAC_LPT;
num_lpt=opcion[4];
}
else if (opcion[0]=='-' && !strcmp(opcion+1,"SBP_MONO"))
disp_salida=SBP_MONO;
else if (opcion[0]=='-' && !strcmp(opcion+1,"SBP_ST"))
disp_salida=SBP_ST;
else if (opcion[0]=='-' && !strcmp(opcion+1,"PROY"))
disp_salida=PROY;
else if (opcion[0]=='-' && !strcmp(opcion+1,"QUIET"))
silenc=1;
else if (opcion[0]=='-' && !strncmp(opcion+1,"EXE",3))
{
strcpy(ejecut,opcion+4);
exe=1;
}
else if (opcion[0]=='-' && !strncmp(opcion+1,"MEM",3))
memoria_total=atol(opcion+4);
else if (opcion[0]=='-' && !strncmp(opcion+1,"NTSC",4))
modo=NTSC;
else
{
printf ("La opción %s es errónea.\n",argv[i]);
exit(1);
}
}
switch (num_lpt)
{
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.98
case '3': num_lpt=LPT3; break;
case '2': num_lpt=LPT2; break;
case '1':
default : num_lpt=LPT1; break;
}
if (disp_salida==NULO || disp_salida==SBP_MONO || disp_salida==SBP_ST)
{
detecta_SB();
if ((sb_puerto==0x22c || sb_puerto==0x24c) && disp_salida!=SBP_MONO)
disp_salida=SBP_ST;
else if (sb_puerto!=0)
disp_salida=SBP_MONO;
else
disp_salida=ALTAVOZ;
}
if (disp_salida==NULO || disp_salida==PROY)
{
detecta_proy();
if (lptdata==0)
disp_salida=ALTAVOZ;
}
prepara_doble_buffer();
prepara_tabla_vol ((disp_salida==SBP_ST || disp_salida==PROY)? 2 : 4);
switch (disp_salida)
{
case DAC_LPT: detecta_LPT (num_lpt);
break;
case SBP_MONO:
case SBP_ST: if (!parametros_SB())
// Carga parámetros de la SB desde
la variable BLASTER
QUIET (printf ("Variable BLASTER no encontrada.\n"))
break;
}
if (memoria_total<64)
{
QUIET (printf ("Error: opción MEM tiene un valor demasiado bajo.\nLa
cantidad de memoria XMS reservada debe ser mayor de 64K\n"));
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.99
exit (1);
}
if (!X_inicia_gestor(memoria_total))
{
QUIET (printf ("Error en la inicialización del gestor de memoria
REALMEM.\n"))
QUIET (printf ("Compruebe que dispone de %uK de XMS y que la CPU no esté en
modo virtual-8086.\n",memoria_total))
exit (1);
}
cambia_frecuencia(letra,modo);
// Asignamos la frecuencia
// Carga el módulo en memoria
modulo=fopen(fmodulo,"rb");
estado=cargar_modulo(modulo);
fclose(modulo);
if (estado)
{
QUIET (printf ("Error durante la carga del módulo.\n"))
QUIET (printf ("El fichero no se encontró o es demasiado grande para caber en
memoria.\n"))
X_fin_gestor();
exit (1);
}
/* le decimos desde donde hay que tocar el modulo */
cont_lin=cont_pat=0;
/* volumenes de cada canal (de 0 a 64) */
volumen1=64;
volumen2=64;
volumen3=64;
volumen4=64;
chivato=1;
// Empieza a sonar la música
PRDISP
init_sampler();
// A partir de ahora, todo lo que se ejecuta se hace con la música en
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. 7.100
background
if (exe)
{
spawnlp(P_WAIT,ejecut,NULL);
terminado=1;
}
while (!terminado)
{
QUIET (printf("Patrón: %02.2d
División: %02.2d
Velocidad: %02.2d
\r",cont_pat,cont_lin,velocidad))
if (kbhit())
{
tecla=getch();
if (tecla==27)
terminado=1;
if (tecla==' ')
hazpausa=!hazpausa;
if (tecla=='s')
{
puts("\n");
QUIET (printf ("Teclea EXIT para volver a TRPLAY\n"))
spawnlp(P_WAIT,getenv("COMSPEC"),NULL);
QUIET (puts("\n"))
PRDISP
}
}
}
putchar('\n');
des_sampler();
borrar_modulo();
// desconectar dispositivo de salida
// borrar módulo de la memoria
X_fin_gestor();
}
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.1
ANEXOS
1.- Bibliografía
La mayoría de la información presentada original del autor. Sin embargo, los siguientes textos se
han utilizado para clarificar, completar o documentar mejor algunos aspectos:
[BIN88]
Bingham, E. O. The fast Fourier transform and its aplications. Ed. Prentice-Hall, 1988
[GRE89]
Gregg, W. D. Analog and digital comunications. Ed. John Wiley, 1989
[RIF91]
J. Rifá-Ll. Hughet. Comunicación digital. Ed. Masson, 1991
[TRA87]
Tran Tien Lang. Electronics of Measuring Systems. Ed. John Wiley, 1987
[RAY88]
Ray Duncan. MS DOS Avanzado. Ed. Anaya Multimedia, 1988
[ROS90]
Miguel Angel Rodríguez-Roselló. 8088/8086-8087 Programación ensamblador en
entorno MS DOS. Ed. Anaya Multimedia, 1988
[ANG90]
J. M. Angulo. Electrónica digital moderna. Teoría y práctica. Ed. Paraninfo, 1990
[INTEL]
Intel Corporation. Datasheets de los circuitos 8253, 8254, 8259A y 8255
[CHR93]
1993
Christian Kuhnert, Stefan Maelger y Johannes Schemmel. Amiga Intern.Ed: Abacus,
El texto del capítulo 3 sobre secuenciamiento musical es original del autor. La información sobre
el estándar MIDI ha sido cedida por [email protected].
La especificación de los archivos MOD se puede encontrar en varios FTP-sites. Uno de los más
idóneos para buscar información sobre estos y otros aspectos del sonido digital es x2ftp.oulu.fi
En concreto, la documentación fue aportada por Andrew Scott (Adrenalin Software). Se puede encontrar
en Internet por [email protected]
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.2
Las descripciones del capítulo 4 son un extracto de los correspondientes data-sheets publicados
por Intel. También se pueden encontrar referencias mediante el programa HelpPC 2.1 que ofrece
documentación en linea de numerosos aspectos de programación y hardware, y que se convirtió en una
valiosa ayuda en la codificación de las rutinas. Este programa se puede encontrar en la ya mencionada
x2ftp.oulu.fi bajo el nombre HELPPC21.ZIP
La discursión sobre el modo real, el protegido y REALMEM proviene de una conferencia en
USENET en el grupo comp.os.msdos.programmers sobre acceder a más de 64K en un segmento. La
documentación aportada incluye la descripción del funcionamiento de la instrucción LOADALL. El texto
entero se puede encontrar en The hyper-space navigator’s guide, de Terrance E. Hodgins. SemiIntelligent Systems PO BOX 4492. ALBURQUERQUE, NM 87196. Al autor se puede acceder vía e-mail
por Internet a terry%[email protected] o por Compuserve en 76416,553
Un extracto del mismo se puede encontrar bajo el nombre REALMEM.ZIP o VIEW-XM.ZIP en
x2ftp.
La información del ADC0820 se tomó de los data-sheets publicados por National Semiconductor.
Además, en x2ftp se pueden encontrar numerosas referencias a los archivos MOD, así como
rutinas con otras características para ejecutar no sólo MOD’s sino también archivos S3M. Para más
información: ftp://x2ftp.oulu.fi/pub/msdos/programming.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.3
2.- Agradecimientos.
El autor desea expresar su agradecimiento a las siguientes personas y asociaciones:
En primer lugar, a mis compañeros Luis Santiago Sánchez Fernández, autor de la presentación
gráfica en el Sampler, Miguel Angel Hinojosa Romero, que cedió el “laboratorio” dónde se hicieron las
primeras pruebas, y que arriesgó valientemente la integridad física de uno de sus dedos mientras soldaba
el segundo prototipo; y a Carmen y Sonia por ayudarles en la ardua tarea.
Al departamento de Arquitectura, especialmente a mi tutor, D. Gabriel Jiménez Moreno, y D.
Antón Civit Balcells, por el apoyo y facilidades prestadas durante el desarrollo de este trabajo.
A la pandilla (nombrarlos a todos sería muy largo), por soportar de ven en cuando mis peroratas
sobre las excelencias del ensamblador y el modo protegido del 386.
A todos los usuarios de galileo.fie.us.es por la ayuda prestada en el testeo del programa y de las
librerías.
A Julio, de R.C.O. por ponerme precios baratitos en los componentes.
A todos los usuarios del grupo comp.os.msdos.programmers de UsNet, y por extensión a todos
los habitantes de Internet que han aportado su colaboración respondiendo a mis cuestiones y aportando
documentación.
A José Angel y Sergio, por colaborar en uno de los prototipos del DAC, y por picarme con el
tema.
A Diego Galán Fernández, cofundador del MMDL allá por el año 1991.
A Rosa Hinojosa por alimentarnos y mantenernos mientras adecentábamos el local.
A Fede ([email protected]) por enseñarnos los secretos de la fabricación de circuitos impresos
por fotografía y por aguantar nuestras idas y venidas del laboratorio.
Y a mi familia, por soportar estoicamente los ruidos que producía el equipo de música mientras
se probaban los prototipos a altas horas de la madrugada.
Y a todos los demás que saben que deberían estar nombrados en esta página (lo siento, creo que
no me he acordado de todos...).
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.4
3.- El altavoz interno. Reproducción de música digital usando la
modulación PWM.
Lo siguiente es un extracto de un artículo que escribió el autor durante la investigación sobre la
posibilidad de usar el altavoz interno del PC para reproducir señales analógicas. Los métodos descritos
en este artículo se han usado en las librerías del reproductor MOD para implementar la reproducción de
4 canales usando también este dispositivo.
Un conversor D/A consta esencialmente de tres bloques funcionales: el primero recoge los datos
digitales que vienen del bus de datos del ordenador desde la memoria y los almacena. El segundo bloque
consta de una serie de interruptores digitales y resistencias conectadas según un determinado tipo de red
en la cual, cuando el bit correspondiente está a 1 se conecta una determinada resistencia al circuito y
cuando está a 0 se conecta otra distinta. Esto provoca que circule por la red una intensidad de valor:
Donde Iref es un valor de intensidad fijado por el hardware y n es el número de bits que se utiliza
en la conversión.
El tercer bloque convierte esta corriente en un valor de tensión proporcional a la intensidad
obtenida y que es la salida final del conversor. Esta tensión puede posteriormente ser amplificada en un
equipo convencional de audio.
Cada dato digital pasa por estos tres bloques para finalmente convertirse en un nivel de tensión
que se mantendrá mientras dure el dato en la memoria del conversor.
Por tanto, la simulación de este proceso implica necesariamente encontrar algún método para que
el altavoz interno del PC sea capaz de darnos cualquier tensión de salida comprendida entre 0 y 5 voltios
y no simplemente estos dos valores extremos.
Para empezar, consideremos qué factores son realmente los que determinan el volumen de sonido
que se escucha en cada momento proveniente de un altavoz. Este es excitado por una tensión V que hace
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.5
que por su bobina circule una intensidad I. Estos dos valores los suministra el amplificador de potencia
y son directamente proporcionales uno respecto del otro. Para trabajar con un único valor, y dado que son
estos dos anteriores los que determinan el volumen de sonido, consideraremos la potencia P=V*I como
factor determinante del volumen de sonido.
Una vez determinado el factor que provoca el que el altavoz dé un determinado volumen se
plantea el problema de como simular este factor. Para ello veamos antes qué podemos hacer con el
altavoz interno del PC.
El altavoz interno del PC sólo puede responder a dos niveles de tensión: una tensión mínima que
corresponde a una nivel lógico 0 y una tensión máxima correspondiente a un nivel lógico 1.
Estos niveles lógicos son entregados a la circuitería del altavoz por dos fuentes digitales distintas:
una de ellas es el timer del PC. Este timer tiene tres contadores, reservándose el tercero de ellos para
provocar impulsos digitales al altavoz.
La segunda fuente es un integrado que realiza varias funciones en el PC: el PPI (un 8042 en el PC AT)
que actúa como interfaz programable para varios periféricos. Controla varias líneas tanto de entrada como
de salida y una de esas líneas va directamente al altavoz [ROS90].
El PPI también se puede programar para elegir la fuente digital que va a actuar sobre el altavoz, utilizando
otra de sus líneas.
Estas dos fuentes nos van a dar distintos resultados según qué tipo de actuación queramos sobre
el altavoz. Utilizando el timer, sólo debemos de preocuparnos por suministrar a éste la frecuencia que
queremos oír. Una vez hecho esto, el timer se encarga de hacer sonar al altavoz con un sonido de esa
frecuencia, mientras que la CPU puede dedicarse a otras tareas. Este método tiene la ventaja de ser
insensible a las variaciones de velocidad de CPU que existe en cada modelo de PC. Por otra parte
utilizando el PPI tenemos completo control sobre que tipo de nivel lógico se entrega al altavoz y por
cuanto tiempo, por lo que puede servirnos para generar señales asimétricas, pero con el inconveniente de
que la CPU debe dedicarse por completo a esta tarea, incluso desactivando las interrupciones para que
el sonido sea limpio.
Independientemente de la fuente que empleemos, lo que está claro es que sólo tendremos dos
tensiones disponibles en el altavoz: la correspondiente al nivel lógico 1, que son 5 voltios, y la
correspondiente al nivel lógico 0, que son 0 voltios.
La cuestión entonces es cómo generar tensiones comprendidas entre 0 y 5 V durante un cierto
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.6
período de tiempo. Para conseguirlo vamos a emplear un método muy parecido al que se emplea en las
fuentes conmutadas de tensión para reducir el valor de la tensión de salida.
Figura A.3.1. Sim ulación de diversos valores de volum en a través del altavoz
interno del PC
En todo lo que sigue, los conceptos de potencia y tensión se tratarán como si fueran equivalentes
(no lo son en realidad, sino que son proporcionales).
En la mitad superior de la figura 4 podemos ver una serie de valores de tensión muestreados
durante un tiempo Tmuestreo. Cada muestra mantiene estable su nivel de tensión durante todo el tiempo de
muestreo, por lo que la potencia (y por tanto el volumen escuchado) será:
Pefectiva=Vefectiva*I
(donde Vefectiva es un valor entre 0 y 5V en nuestro ejemplo)
Para conseguir esta misma cantidad de potencia en el mismo tiempo, pero con una tensión
exclusivamente de 0 ó 5V, debemos mantener 5V durante un tiempo determinado que llamaremos Talto,
menor que el tiempo de muestreo, para luego conmutar bruscamente a 0V y mantener esta tensión durante
el resto del tiempo que dura la muestra (Tbajo). Así, la potencia entregada al altavoz será:
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.7
Pefectiva = 5V * Talto + 0V * Tbajo
Donde Talto y Tbajo no se dan como tiempos en sí, sino como fracciones del tiempo de muestreo
total. De esta manera, para conseguir una tensión de 2,5V (o su nivel de potencia correspondiente) habrá
que mantener 5V durante la primera mitad del tiempo de muestreo, y 0V durante la segunda mitad. En
general, para mantener una tensión V cuyo valor está comprendido entre Vmin y Vmax durante un tiempo
Tmuestreo, los valores de Talto y Tbajo serán:
Para conseguir estos tiempos es recomendable utilizar el timer del PC, con el que conseguimos
que la CPU esté ocupada el menor tiempo posible en la generación del sonido. La señal resultante se
denomina señal PWM (Modulación por Anchura de Pulso).
Como ejemplo de todo lo expuesto vamos a utilizar la versión 2.0 del Turbo Assembler de
Borland para desarrollar un programa que lea ficheros de muestras (por ejemplo, los .VOC de la Sound
Blaster) y los reproduzca por el altavoz. No hay limitación en la longitud de los mismos.
El ejemplo asume que se está trabajando sobre un AT 286 a 16 MHz como mínimo, pero es
posible que funcione bien en máquinas más lentas. Concretamente, se puede modificar el código para que
corra en un XT (esto afectaría a las órdenes SAR, SAL, PUSHA y POPA).
Para utilizarlo, teclear VOC nombre_de_fichero
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.8
;Fichero VOC.ASM
;Programa para leer muestras del tipo VOXKIT de tamaño ilimitado
;(c) 1992 Miguel Angel Rodríguez Jódar
.286
;usamos el juego de instrucciones del 80286
lonbloque
equ 65500
;longitud de los dos buffers
puntero
offs
segm
puntero
struc
dw ?
dw ?
ends
;Estructura para almacenar un puntero largo
;Macro para inicializar el contador 2 que maneja el altavoz. Se programa en
;modo 0 (port 43h) y se da la orden al PPI para que conmute al modo de altavoz
;controlado por timer (port 97h)
init_timer
macro
mov al,10110000b
out 43h,al
in al,97
or al,3
out 97,al
endm
;Esta macro desconecta el altavoz del timer para que no suene más.
quit_timer
macro
in al,97
and al,0fch
out 97,al
endm
;Pila del programa.
pila
segment stack
db 20 dup ('PILA')
pila
ends
;*****************************************************************************
;*
*
;*
S E G M E N T O
D E
D A T O S
*
;*
*
;*****************************************************************************
datos
segment
nombre
db 100 dup(0)
men1
db 'ERROR!!. Necesito 130000 bytes libres de RAM para funcionar.'
db 13,10,'$'
men2
db 'Fichero no encontrado.',13,10,'$'
men3
db 'Ejecutor de módulos VOXKIT por el altavoz interno v1.0',13,10
db '(c) 1992 Miguel Angel Rodríguez Jódar. Sevilla, 22 de Agosto de'
db '1992',13,10
db 'Teclas:1 y 2: sube/baja la frecuencia de muestreo',13,10
db 'Teclas 3 y 4: sube/baja el volumen',13,10
db 'ESC: volver al DOS',13,10,13,10,'$'
finfich
db 0
;vale 1 si se ha llegado al fin de fichero.
hayescape
db 0
;vale distinto de 0 si se pulsó la tecla ESC
handle
dw 0
;mantiene el valor del handle suministrado por MS-DOS.
empezado
db 0
;vale 1 si se ha empezado a reproducir sonido desde uno
;de los bufferes.
terminado
db 0
;vale 1 si se ha terminado de reproducir sonido desde uno
;de los bufferes.
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
periodo
db 100
volumen
muestra1
muestra2
ant08
ant09
mact
datos
db 255
puntero
puntero
puntero
puntero
puntero
ends
Pag. A.9
;tiempo de muestreo. La frecuencia de muestreo es
;
1193180/periodo (Hz)
;Volumen del sonido (0-255)
<0,0>
;puntero al primer buffer
<0,0>
;puntero al segundo buffer
<?,?>
;almacen temporal de la antigua int 8
<?,?>
;
"
"
"
"
"
" 9
<?,?>
;puntero al buffer actual
;*****************************************************************************
;*
*
;*
S E G M E N T O
D E
C O D I G O
*
;*
*
;*****************************************************************************
codigo
tocavoc
segment
assume cs:codigo,ss:pila,ds:datos,es:datos
proc far
call pon_nombre
bien1:
bien2:
bien3:
;obtener nombre del fichero
mov bx,300
mov ah,4ah
int 21h
;limitar la memoria asignada al programa
mov ax,datos
mov ds,ax
;direccionar el segmento de datos
mov
mov
int
jnc
jmp
mov
mov
mov
mov
int
jnc
jmp
mov
mov
bx,4096
ah,48h
21h
bien1
nomemo
muestra1.segm,ax
muestra1.offs,0
bx,4096
ah,48h
21h
bien2
nomemo
muestra2.segm,ax
muestra2.offs,0
mov
mov
int
jnc
jmp
mov
mov
mov
int
ax,3d00h
dx,offset nombre
21h
bien3
errorfich
handle,ax
ah,9
dx,offset men3
21h
mov ax,muestra1.segm
call carga
mov ax,3508h
;
;
;
;
;
;Reservar memoria para los dos
;buffers. Si no hay suficiente, salir
;del programa por la etiqueta nomemo
;
;
;
;
;
;
;abrir fichero para lectura
;si no se pudo, error
;cargar el primer buffer con los primeros
;64K de muestras.
;
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
bucprin:
noempez:
carga_2:
sigue:
termino:
int 21h
mov ant08.offs,bx
mov ant08.segm,es
mov ax,3509h
int 21h
mov ant09.offs,bx
mov ant09.segm,es
push ds
mov dx,offset int08
mov ax,seg int08
mov ds,ax
mov ax,2508h
int 21h
mov dx,offset int09
mov ax,seg int09
mov ds,ax
mov ax,2509h
int 21h
pop ds
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
init_timer
mov al,periodo
out 40h,al
xor al,al
out 40h,al
mov ax,muestra1.segm
mov mact.segm,ax
sti
;inicializar timer
;cargar periodo en el contador de la int 8
mov terminado,0
cmp hayescape,0
jne cortavoc
cmp empezado,0
je noempez
mov al,finfich
inc finfich
or al,al
jnz sigue
mov ax,mact.segm
cmp ax,muestra1.segm
je carga_2
push ax
call carga
pop ax
jmp sigue
mov ax,muestra2.segm
push ax
call carga
pop ax
mov empezado,0
cmp hayescape,0
jne cortavoc
cmp terminado,0
je termino
mov mact.segm,ax
mov mact.offs,0
;inicializa terminado para este buffer
;Si se pulsó ESC...
;sal inmediatamente del bucle de ejecución
;mientras no empieze a leer muestras
;sigue esperando
cmp finfich,2
jne bucprin
Pag. A.10
Asignar a los vectores 8 y 9 las
nuevas rutinas de tratamiento
almacenando antes la dirección de
las anteriores.
;hacer buffer actual = buffer_1
;permitir interrupciones
;si se alcanzo fin de fichero
;no cargues más de disco
;
;
;Carga el siguiente bloque en el buffer
;que NO se está utilizando ahora
;
;
;
;
;
;
;
;inicializa empezado para el próximo buffer
;si no se ha terminado de ller el buffer
;sigue esperando
;el buffer actual es ahora aquél en el que
;se cargó por última vez
;si no se ha alcanzado el fin de fichero
;sigue cargando y leyendo
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
cortavoc:
cli
quit_timer
xor al,al
out 40h,al
jmp $+2
out 40h,al
push ds
lds dx,dword ptr ant08
mov ax,2508h
int 21h
pop ds
push ds
lds dx,dword ptr ant09
mov ax,2509h
int 21h
pop ds
sti
mov
mov
int
mov
mov
mov
int
mov
mov
mov
int
bx,handle
ah,3eh
21h
ax,muestra1.segm
es,ax
ah,49h
21h
ax,muestra2.segm
es,ax
ah,49h
21h
call ponreloj
fintoca:
mov ax,4c00h
int 21h
Pag. A.11
;
;
;
;
;
;
;
;Reponer los vectores de interrupción antiguos
;
;
;
;
;
;
;
;
;
;cerrar fichero
;liberar la memoria de los buffers
;actualizar reloj del sistema
;(que se quedó parado).
;salida al DOS
nomemo:
mov
mov
int
jmp
dx,offset men1
ah,9
21h
fintoca
;salida al DOS con mensaje de no hay
;memoria
errorfich:
mov
mov
int
jmp
dx,offset men2
ah,9
21h
fintoca
;salida al DOS con mensaje de fichero
;no encontrado
tocavoc
endp
;Este procedimiento copia el primer argumento de la línea de órdenes
;en la variable "nombre"
pon_nombre
proc
cld
push es
mov ax,datos
mov es,ax
mov di,offset nombre
mov si,128
;offset de los parámetros en el PSP
mov cl,[si]
;carga longitud de los parámetros
or cl,cl
;si no se teclearon parámetros, salir
jz nonombre
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
nonombre:
pon_nombre
dec cl
xor ch,ch
inc si
inc si
rep movsb
pop es
ret
endp
Pag. A.12
;copia nombre de fichero en la variable 'nombre'
;Este procedimeinto carga 65500 bytes del fichero empezando en
;la posición AX:0
carga
proc
mov finfich,0
push ds
push ax
push ax
mov bx,handle
pop ds
pop es
mov
mov
mov
mov
rep
fincarga:
carga
si,0
word ptr [si],0
di,2
cx,lonbloque/2
movsw
mov dx,0
mov cx,lonbloque
mov ah,3fh
int 21h
pop ds
cmp ax,lonbloque
je fincarga
mov finfich,1
ret
endp
;Nueva interrupción del teclado
int09
proc
cli
push ax
push ds
mov ax,datos
mov ds,ax
in al,60h
push ax
and al,7fh
cmp al,1
jne fintecla
pop ax
mov hayescape,1
jmp finint09
fintecla:
pop ax
cmp al,2
jne noes1
mov al,periodo
cmp al,20
je finint09
;si se pulsó ESC...
;si se pulsó "1"
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
dec al
mov
out
xor
out
jmp
noes1:
noes2:
Pag. A.13
;decrementa el periodo (aumenta la
;frecuencia de muestreo) y cárgala en el
;contador 0 del timer.
periodo,al
40h,al
al,al
40h,al
finint09
cmp al,3
jne noes2
mov al,periodo
cmp al,255
je finint09
inc al
mov periodo,al
out 40h,al
xor al,al
out 40h,al
cmp al,4
;si se pulsó "2" incrementa el período.
;"3" y "4" hacen las mismas operaciones
;con la variable volumen
jne noes3
mov al,volumen
cmp al,255
je finint09
inc volumen
jmp finint09
noes3:
cmp al,5
jne finint09
mov al,volumen
or al,al
jz finint09
dec volumen
finint09:
mov al,20h
out 20h,al
pop ds
pop ax
sti
iret
endp
int09
;mandar un EOI al 8259-A
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.14
;Esta es la interrupción 8. Se llama 1193180/periodo veces por segundo. Cada
;vez que se ejecuta lee una muestra del buffer actual y la manda por el altavoz
;interno utilizando el método expuesto. Para conseguir los tiempos
;Talto y Tbajo se programa el contador 2 (port 42h) en modo 0. Este modo hace
;que cuando se le cargue un valor (entre 0 y periodo), ponga su salida a 0
;durante ese valor, para luego ponerla a 1 el resto del tiempo hasta que se
;le vuelva a cargar otro valor. El contador 2 se conecta al altavoz mediante
;la macro "init_timer".
int08
proc
cli
pusha
push ds
push es
mov ax,datos
mov ds,ax
mov ax,mact.segm
mov es,ax
mov si,mact.offs
or si,si
jnz noes0
mov empezado,1
noes0:
cmp si,lonbloque
jne noesult
mov terminado,1
noesult:
mov al,es:[si]
;cargamos una nueva muestra en al
inc mact.offs
mul volumen
xor dx,dx
mov bx,128
div bx
;ax=muestra*volumen/128
cmp ax,255
;si ax>255...
jbe ponper
mov al,255
;entonces ax=255
ponper:
mul periodo
sar ax,8
;al (Talto) =muestra*periodo/256
out 42h,al
xor al,al
out 42h,al
;carga Talto en el contador 2
mov al,20h
out 20h,al
int08
;mandar EOI
pop es
pop ds
popa
sti
iret
endp
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995
MULTIMEDIA en PC. Emulación del hardware de audio del Commodore Amiga. Digitalizador y reproductor estéreo de sonido digitalizado.
Pag. A.15
;Este procedimiento toma la hora real del reloj CMOS y la coloca en el reloj de la BIOS.
;Esto se hace para poner de nuevo en hora el reloj del sistema que se paró mientras se
;ejecutaba el programa.
ponreloj
proc
mov ah,2
int 1ah
mov al,ch ;Convertir horas
call convt
mov ch,al
mov al,cl ;Convertir minutos
call convt
mov cl,al
mov al,dh ;Convertir segundos
call convt
mov dh,al
xor dl,dl
mov ah,2dh
int 21h
ret
ponreloj
endp
convt
proc
push cx
mov ah,al
and al,0fh
and ah,0f0h
mov cl,4
shr ah,cl
aad
pop cx
ret
convt
endp
codigo
ends
;al <-- unidades
;ah <-- decenas
end tocavoc
Miguel Angel Rodríguez Jódar. Departamento de álgebra y computación. Facultad de Informática y Estadística. Sevilla, 1995