Programación en X68000 capítulo 5, Reproduciendo sonido digital.
Introducción:
En este capitulo voy a explicar como generar ficheros de sonido digital compatibles con X68000 y como reproducirlos con algunas demos.
El X68000 esta equipado con el chip Oki MSM6258 ADPCM que lo capacita para codificar y decodificar ficheros de sonido en formato Adaptive Differential Pulse-code Modulation (ADPCM).
El formato ADPCM depende de cada fabricante, cada compañía tiene el suyo propio de modo que necesitamos una manera de codificar sonido en el formato especifico con el que trabaja el X68000.
Para seguir este tutorial necesitaras algunos programas. Asumiré que tienes Git, el entorno de desarrollo de X68000 correctamente instalado. Si no lo tienes aún puedes seguir estos dos artículos:
PROGRAMACIÓN EN X68000 CAPÍTULO 2.1, INSTALACIÓN DEL ENTORNO DE PROGRAMACIÓN. SABOR LYDUX
PROGRAMACIÓN EN X68000 CAPÍTULO 2.2, INSTALACIÓN DEL ENTORNO DE PROGRAMACIÓN. SABOR JASON STEVENS
El entorno de desarrollo en esos artículos es CodeBlocks el cual trae MinGW como compilador GCC.
Construiremos desde el código fuente el programa que necesitamos para convertir WAV crudo en ADPCM crudo.
También necesitarás Audacity que es un programa de código abierto para edición de audio digital.
Entendiendo el sonido digital.
Antes de ponernos manos a la obra creo que es importante una introducción al sonido digital.
El sonido es un fenómeno físico que ocurre cuando la energía se propaga a través del aire en forma de ondas de presión de aire. Estas ondas son el sonido que escuchamos.
En la naturaleza las ondas analógicas y son representadas por valores continuos lo que significa que entre os valores puede haber infinitos valores mas pequeños.
Los ordenadores son máquinas que trabajan con valores discretos lo que significa que entre dos valores hay valores que no pueden ser representados, por lo tanto parte de la información del reino de lo analógico se pierde.
Cuando se digitaliza sonido los ordenadores cogen muestras o fotos de estos valores a intervalos regulares llamados frecuencia y estos valores, los cuales son la amplitud de las ondas, son representados por un número con precisión limitada.
Probablemente estés familiarizado con los términos 44100 Hz 16bit calidad de CD. Esto significa que para alcanzar la calidad de CD necesitamos 44100 muestras por segundo, es decir, 44100 rebanadas de las ondas cada segundo y que cada rebanada se representa con un número entero de 16 bits con signo.
Con estos dos valores podemos dibujar una onda con una “resolución” de 44100 por 65,535 teniendo en cuenta que esto valores de 16 bits tienen signo por tanto están entre -32,768 y 32,767.
Adaptive Differential Pulse-code Modulation (ADPCM)
Siguiendo con el ejemplo de la calidad de CD de antes, almacenar un segundo con tal frecuencia de muestreo y profundidad de bits requiere 88200 bytes por canal. Sonido mono mientras que Estero usa dos.
Por lo tanto un minuto son sobre 5 megabytes por canal. Esto es el porqué no almacenamos sonido digital en formatos crudos sino que los comprimimos en MP3 u otros formatos para ahorrar espacio en disco.
Antiguamente, en los días del X68000 no teníamos MP3 sino formatos crudos y la capacidad de almacenamiento era un lujo.
Hay otra forma de representar formas de onda digitalmente y eso con Adaptive Differential Pulse-code Modulation (ADPCM).
En vez de almacenar la amplitud de onda de cada muestra lo cual toma 2 bytes por cada una de ellas, almacenamos el “delta” que es la diferencia entre una muestra y la siguiente.
Las diferencias entre muestras se pueden representar con valores mas pequeños la mayoría de las veces.
Aún podríamos tener escenarios done la diferencia entre dos muestras requiera los 2 bytes.
Para solventar este problema ADPCM implementa una tabla con los 50 valores mas comunes entre muestras. Estos valores son realmente aproximaciones y son diseñados para ajustarse a ciertos requerimientos del sonido.
Así que en vez de almacenar amplitudes o diferencias entre muestras, almacenamos índices de esta tabla por muestra lo que toma menos de un byte y ahora espacio al coste de perder algo de información pero aún con una calidad aceptable.
Cada fabricante tenia su propia tabla para cubrir sus propias necesidades y para X68000 el fabricante era Oki y la tabla esta implementada en el chip Oki MSM6258 ADPCM.
Software requerido
Ahora que sabemos como funciona el sonido digital y que necesitamos producirlo en formato ADPCM ya podemos ponernos manos a la obra.
Conversor de WAV a ADPCM.
Lo primero de todo, necesitamos un programa que convierta ondas de enteros de 16 bits con signo en ADPCM compatible con X68000.
Encontré en github un programa en https://github.com/superctr/adpcm el cual ha sido desarrollado por el usuario superctr y es de dominio público.
Como primer paso necesitamos compilar este programa.
git clone https://github.com/superctr/adpcm cd adpcm make
Si estás en Windows y tienes MinGW64 puedes ejecutar mingw32-make en vez de make.
Ahora deberíamos tener el adpcm.exe
Audacity
Si aún no tienes Audacity lo puedes descargar gratis de:
https://www.audacityteam.org/download/
Convertir un fichero de sonido en formato ADPCM de X68000
En Audacity podemos grabar sonido o podemos abrir algún fichero de sonido como WAV o MP3.
De cualquier manera necesitamos tener en cuenta que si el sonido tiene que caber en un disquete deberíamos trabajar con no mas de 2 minutos y medio. Esto es porque el fichero resultante ocupara mas o menos 469014 bytes por minuto.
Una vez que tenemos el audio ya sea por el micrófono o de alguno formato de audio el primer paso es asegurarse que está en mono ya que X68000 reproduce música ADPCM en mono.
Para hacer esto necesitamos seleccionar la opción: Track / Mix / Mix stereo down to mono
X68000 soporta las siguientes frecuencias de muestreo: 3.9Khz, 5.2Khz, 7,8Khz, 10,4Khz y 15,6Khz.
En nuestro ejemplo vamos a usar el mas alto, los 15.6 Khz de modo que necesitamos remuestrear el sonido a esa frecuencia de muestreo.
Hacemos Track/Resample
e introducimos el numero 15600 en el dialogo.
Ahora necesitamos poner que el audio es 44100 otra vez aunque no lo sea. Click derecho en la pista y selecciona 44100.
Si ahora reprodujésemos el sonido sonaría casi tres veces mas rápido. Poner la frecuencia como si fuese 44100 es necesario para que el programa adpcm.exe codifique el sonido correctamente. Si lo dejásemos como 15600 se codificaría y sonaría 3 veces mas despacio en el X68000.
Ahora tenemos que exportar el sonido. Hacemos File / Export / Export Audio
Y en el dialogo seleccionamos un directorio, idealmente donde está el programa adpcm.exe, y en el desplegable header seleccionamos RAW (header-less) y en el desplegable encoding Signed 16 - bit PCM.
En el siguiente paso vamos a codifica el sonido que acabamos de exportar como Raw (header-less) Signed 16bit en el ADPCM de Oki usando el programa adpcm.exe que compilamos antes.
Si abrimos una consola de comando y vamos donde adpcm.exe está y lanzamos adpcm veremos sus opciones:
Como vemos, podemos codificar el fichero en varios formatos entre los cuales tenemos Oki X68000 (MSM6258).
Solo tenemos que lanzar el siguiente comando:
adpcm.exe xe music.raw result.raw
Esto debería generar el fichero result.raw en el formato que X68000 puede entender.
Ahora, para reproducir el sonido necesitamos un programa en el X68000.
En mi github tengo 3 programas que pueden reproducir este fichero en las direcciones:
https://github.com/FedericoTech/X68KTutorials/tree/main/ADPCM
https://github.com/FedericoTech/X68KTutorials/tree/main/ADPCM2
https://github.com/FedericoTech/X68KTutorials/tree/main/ADPCM3
Hay dos fichero, ADPCM.cbp el cual es el fichero de proyecto en Codeblocks y main.c el cual es el programa.
Descarga ambos y compila lo para X68000 con Codeblocks.
Ahora, si tiene un X68000 original puedes intentar copiar el programa generado ADPCM.x y el fichero de audio result.raw en un disquete.
Si como mas probablemente no tienes el ordenador origina, necesitarás un emulador.
Con XM6-Pro puedes poner el ejecutable ADPCM.x y el fichero result.raw en un directorio y montarlo como si fuese un disquete.
Ya sea que tengas el X68000original o el XM6-pro, necesitas ir a la unidad:
B:
y lanzar el programa con el comando:
adpcm
Explicación del programa
Si estudias el código fuente veras que abrimos el fichero con _dos_open, después comprobamos el tamaño con _dos_seek, y asignamos memoria con _dos_malloc con espacio para dos cachos de música. El X68000 puede reproducir música en cachos de 65280 bytes por lo que reservamos 130560 bytes.
Con _dos_read cargamos el primer pedazo desde el disquete.
Después empezamos un bucle que se repite en tanto que no hayamos terminado de reproducir el sonido.
En cada vuelva reproducimos un pedazo de musica con la función _iocs_adpcmout(buffer, mode, size)
Buffer is la dirección donde la música empieza.
Mode is una palabra de 16 bits de flags donde decimos con flags cosas como la frecuencia de muestreo, si queremos reproducir el sonido en ambos altavoces, el altavoz izquierdo, el altavoz derecho o ninguno.
Recuerda que la música en si misma es en mono pero podemos redirigirla a un altavoz o los dos.
Size es la cantidad de datos que queremos enviar. Es importante decir que si el tamaño es 65280 o menos, el retorno será inmediato y podemos haber otras cosas mientras se reproduce la música, pero si es mas, la CPU esperara y no podremos ejecutar ninguno código hasta que la música se detenga.
En este programa el bucle principal carga dos cachos de música alternativamente cada vez para alimentar _iocs_adpcmout. Como el pedazo no es mas grande que 65280 bytes podemos ejecutar el bucle while anidado que muestra si la música está sonando.
Podemos comprobar si la música suena con la función _iocs_adpcmsns la cual nos dice el estado actual de la música. En nuestro bucle comprobamos si no esta inactivo.
Dentro del bucle comprobamos si alguna tecla del teclado ha sido presionada con la linea:
if(_dos_inpout(0xFF) != 0). Si ha sido así salimos de los dos bucles.
Si la función _iocs_adpcmsns dice que la música ha finalizado, alimentamos _iocs_adpcmout con el siguiente pedazo hasta que no quede ningno.
Los otros dos programas ADPCM2 y ADPCM3 de mi github son versiones que también tocan la música pero haciendo uso de las funciones _iocs_adpcmaot y _iocs_adpcmlot respectivamente.
Si enviamos de hasta 65280 bytes podemos dejar la música sonando por si sola y tenemos la CPU disponible para ejecutar algo a la vez. Esto es posible porque las funciones _iocs_adpcmout, _iocs_adpcmaot y_iocs_adpcmlot hacen uso del canal DMA que libera a la CPU de mover datos de la memoria al dispositivo de música.







Comentarios