Download Emulación del hardware de audio del Commodore Amiga
Document related concepts
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(¬a); 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 (" rodriguj@risc36.fie.us.es or rodriguj@150.214.141.36\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 yish@cs.huji.ac.il. 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 ascott@tartarus.uwa.edu.au 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%scopes.unm.edu@ariel.unm.edu 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 (fede@teclix.fie.us.es) 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