[OpenBSD]

Cómo portar aplicaciones de audio a OpenBSD

En la actualidad este documento sólo trata sobre temas relacionados con muestras de sonido, pero se aceptan contribuciones sobre sintetizadores y tablas de ondas.

Las aplicaciones de audio suelen ser difíciles de portar ya que éste es un terreno en donde no existen normativas que regulen las interfaces, aunque no existe mucha diferencia entre cómo se aborda el tema en diferentes sistemas operativos.

Utilización de ossaudio

La emulación ossaudio es la posibilidad más simple, pero no siempre funciona y generalmente no es una buena idea.

Utilización de código de NetBSD o FreeBSD ya existente

Como compartimos parte de la interfaz de audio con NetBSD y FreeBSD, comenzar con un porte de NetBSD es razonable. Hay que tener cuidado por que algunos ficheros cambian de sitio, y algunas entradas en sys/audioio.h son obsoletas. Además, muchos portes tienden a estar codificados de modo incorrecto y sólo funcionan en un tipo de máquina. Algunos cambios son necesarios. Siga leyendo.

Cómo escribir código de OpenBSD

Independencia del hardware

NO SE DEBE ASUMIR NADA SOBRE EL HARDWARE DE AUDIO QUE SE UTILICE
Código incorrecto es el código que sólo verifica el campo a_info.play.precision con 8 ó 16 bits, y que asume como buenas las muestras de audio firmadas o no, basándose en el comportamiento de soundblaster. Siempre se debe verificar el tipo de muestra de modo explícito, y codificar de acuerdo con ésta. Un ejemplo simple:

AUDIO_INIT_INFO(&a_info);
a_info.play.encoding = AUDIO_ENCODING_SLINEAR;
a_info.play.precision = 16;
a_info.play.sample_rate = 22050;
error = ioctl(audio, AUDIO_SETINFO, &a_info);
if (error)
	/* deal with it */
error = ioctl(audio, AUDIO_GETINFO, &a_info);
switch(a_info.play.encoding)
	{
case AUDIO_ENCODING_ULINEAR_LE:
case AUDIO_ENCODING_ULINEAR_BE:
	if (a_info.play.precision == 8)
	    /* ... */
	else 
	    /* ... */
	break;
case ...

default:
	/* don't forget to deal with what you don't know !!! For instance, */
	fprintf(stderr, 
		"Unsupported audio format (%d), ask ports@ about that\n",
		a_info.play.encoding);

	}
/* now don't forget to check what sampling frequency you actually got */

Esto viene a ser el fragmento de código más pequeño con que se tendrá que tratar en la mayoría de casos.

Formatos de 16 bits y "endian"

Para uso normal simplemente se pide el tipo de condificación (v.g., AUDIO_ENCODING_SLINEAR) y se saca una codificación con tipo de "endian" (v.g., AUDIO_ENCODING_SLINEAR_LE).

Teniendo en cuenta que una tarjeta de sonido no tiene que usar el mismo tipo de "endian" que la plataforma, hay que estar preparado para esto. El modo más fácil es, probablemente, preparar una memoria intermedia de audio entera, y usar swab(3) si se requiere un cambio del tipo de "endian". Al tratar con muestras externas suele ser:

  1. analizar el formato de la muestra,
  2. introducir la muestra,
  3. cambiar el tipo de "endian" si no corresponde al de nuestro formato,
  4. computar la salida deseada en la memoria intermedia,
  5. cambiar el tipo de "endian" si la tarjeta de sonido no corresponde a nuestro formato,
  6. y jugar con la memoria intermedia.

Si se está jugando con una muestra de sonido que se encuentra en el formato de la tarjeta de sonido, se pueden eliminar los pasos 3 y 5.

Calidad de audio

El hardware puede tener unas limitaciones extrañas, como que no pueda obtener más de 22050 Hz en estéreo y sin embargo obtenga hasta 44100 en mono. En casos como éste y similares hay que ofrecer un cambio al usuario para que escoja sus preferencias, e intentar dar el mejor rendimiento posible. Por ejemplo, sería estúpido limitar la frecuencia a 22050 Hz ya que la salida es en estéreo. ¿Y si el usuario no tiene un sistema de sonido en estéreo conectado a la salida de su tarjeta de audio?

También sería estúpido codificar las limitaciones de soundblaster en su programa. Intente sobrepasar la barrera de 22050 Hz/stereo y verifique los resultados.

Muestras de frecuencia

Las muestras de frecuencia devueltas por la tarjeta de sonido siempre deben ser verificadas. Una discrepancia del 5% es medio tono, y algunas personas tienen un oído más fino que eso, aunque la mayoría de nosotros no notemos nada. Su aplicación debería ser capaz de llevar a cabo un «remuestreo» al instante, posiblemente de forma nativa o a través de aplicaciones de «remuestreo» de Shannon.

Campo dinámico

Los muestreos no siempre usan el campo de valores entero. Primero, las muestras grabadas con un volumen bajo no sonarán muy altas en la máquina, forzando al usuario a subir el volumen. Segundo, en máquinas con audio mal aislado, la salida de sonido bajo significa que la mayor parte de lo que se oye es el latido de la máquina y no el sonido esperado. Finalmente, la conversión muda de 16 bits a 8 bits le puede dejar con tan sólo 4 bits de audio utilizables, lo que da como resultado una pésima calidad.

Si es posible, la mejor solución está en escanear todo lo que se vaya a escuchar con anterioridad, y ponerlo en escala de modo que entre dentro del campo dinámico. Si no se puede permitir esto pero puede planear con anterioridad lo que vaya a escuchar, puede ajustar la potencia del volumen; sólo debe asegurarse de que el factor de potencia se mantiene en una frecuencia baja en comparación con la del sonido que quiera escuchar, y que no haya ningún desbordamiento (éstos siempre sonarán mucho peor que la mejora que intente conseguir).
Ya que la percepción del volumen del sonido es logarítmica, generalmente bastará con usar cambios aritméticos. Si sus datos están firmados, debería codificar el cambio de forma explícita como una división, ya que el operador de C >> no se puede portar a datos firmados.

Si lo demás fallara, debería por lo menos intentar proveer al usuario con una opción escalable de sonido.

Rendimiento del audio

Las aplicaciones de poca demanda no deben preocupar mucho. Tenga en cuenta que algunos de nosotros usamos OpenBSD en 68030 de baja demanda, y que si una aplicación de sonido puede funcionar, debería hacerlo.

No se olvide de llevar a cabo bancos de pruebas. Las optimizaciones teoréticas son sólo eso: teoría. Debería recolectar algunas cifras para poder comprobar qué se puede mejorar ampliamente y qué no.

Para aplicaciones de audio de alto rendimiento, como mpegI-layer3, hay que tener en consideración algunos puntos:

Un modelo que es posible que tenga que seguir para obtener resultados óptimos es el de compilar primero un pequeño programa de pruebas que investigue sobre el hardware de audio disponible, y entonces pasar a configurar su programa de modo que trate de forma óptima con este hardware. Se puede asumir que los usuarios que esperan unos resultados de audio buenos recompilarán su porte cuando cambien de hardware.

Tiempo real o sincronizado

Aun cuando OpenBSD no sea un sistema en tiempo real, es posible programar aplicaciones de audio para tiempo real, como puedan ser juegos. En tal caso es necesario rebajar el tamaño de los bloques para que los efectos de sonido no se desincronicen con el juego. El problema con esto es que el dispositivo de audio puede sufrir «inanición», lo que daría unos resultados terribles.

Si solamente quiere sincronizar el audio con la salida de algunos gráficos, pero se puede predecir el comportamiento de su programa, es más fácil alcanzar la sincronización. Ejecute las muestras de audio y pregunte al dispositivo de audio qué es lo que está ejecutando con AUDIO_GETOOFFS, y entonces use esa información para postsicronizar los gráficos. Si se lo pide con bastante frecuencia (digamos que cada décima de segundo), y siempre que tenga suficiente potencia para ejecutar su aplicación, puede obtener una sincronización bastante buena de este modo. Es posible que tenga que trastocar un poco las cifras por una constante de contrapeso, ya que existe desincronización entre los informes del audio, lo que se está ejecutando, y el tiempo que tarda XWindow en mostrar algo.

Aportación del código

En el caso de las aplicaciones de audio, trabajar con el autor del programa original es muy importante. Si su código sólo funciona, por ejemplo, con tarjetas soundblaster, es muy posible que tenga que tratar con otra tecnología en breve.

Si no le envía sus comentarios en ese momento, el trabajo que Vd. haga habrá sido en vano.

También es posible que el autor ya se haya dado cuenta de los problemas con los que esté tratando y que esté trabajando en ellos en su árbol de desarrollo actual. Si los parches que Vd. está escribiendo son de más de un par de líneas, es una buena idea que intente cooperar.


Porting www@openbsd.org
Originally [OpenBSD: audio-port.html,v 1.8 2003/03/06 13:51:31 naddy Exp ]
$Translation: audio-port.html,v 1.12 2003/03/09 21:32:48 horacio Exp $
$OpenBSD: audio-port.html,v 1.11 2003/03/11 09:33:16 jufi Exp $