Herramientas de usuario

Herramientas del sitio


tutorial_de_ensamblador_sonido

Hola Sonido

El sonido de la GameBoy es un tema complejo si vienes de programar en un sistema moderno donde simplemente reproduces sonido digital, mezclando fácilmente música y efectos. La GameBoy por el contrario, tiene un hardware de sonido bastante sencillo, formado por cuatro canales independientes y diferentes entre si. Podemos controlar estos canales a nuestro antojo, que la GameBoy se encargará de mezclarlos. Estos cuatro canales se manejan escribiendo valores en registros mapeados en memoria (cómo no), y cada canal cuenta con varios registros para cada uno de sus parámetros, asi que el tema lleva un rato explicarlo. Vamos a conocer los canales y luego veremos como se programan.

  • Canal 1: El canal 1, es un canal de onda cuadrada con ciclo de trabajo modificable, con envolvente y portamento.
  • Canal 2: Es un canal de onda cuadrada con ciclo de trabajo modificable, con envolvente.
  • Canal 3: Canal de onda programable con una tabla RAM de 32 pasos.
  • Canal 4: Canal de ruido blanco con envolvente.

Bien, para empezar, voy a explicar un poco de teoria musical, bueno, sólo lo que nos interesa, el ciclo de trabajo, la envolvente y el portamento.

El ciclo de trabajo, es algo muy sencillo, si tenemos que la onda es cuadrada, es simplemente cuanto del tiempo de la duración de la nota, tenemos el nivel alto, y cuanto tiempo el nivel bajo. Esto se expresa en tanto por ciento. Asi en la GamebBoy podemos elegir ciclos de trabajo del 12,5%, 25%, 50%, y 75%. Vamos a explicarlo con una imagen robada de por ahi:

Como veis, las ondas tienen la misma frecuencia (todas empiezan en el mismo momento), pero dependiendo del ciclo de trabajo, unas se pasan más tiempo arriba y otras más tiempo abajo.

La envolvente de una nota, es una función que se aplica a la amplitud de esta, para modificarla y que varie a lo largo de la duración de la misma. En síntesis, se suele usar una envolvente conocida como ADSR, de Attack, Decay, Sustain y Release, es decir, ataque, decaimiento, sostenimiento y relajación. Vamos a poner un gráfico… wikipedia al rescate. Si tenemos que una nota normal, tendria cierta amplitud (volumen) fija, la gráfica de su amplitud, sería una linea recta. Ahora si le aplicamos una envolvente ADSR modelo, tendriamos algo como esto:

Con lo que viendo esto, podemos decir, que, el ataque, es el tiempo que tarda la nota en llegar hasta su máxima amplitud, el decaimiento, es el tiempo que tarda en pasar desde el fin del ataque, hasta el valor de sostenimiento, que es el valor de amplitud que mantenemos hasta el fin de la nota, y la relajación, el tiempo que tarda la nota en “desaparecer” desde que la acabamos de tocar. Con todos estos parámetros de envolvente, podemos modelar las notas de manera que cambien bastante aunque estemos tocando la misma frecuencia. Lamentablemente la envolvente de la GameBoy es mucho más sencilla, sólo nos permite definir un valor inicial de amplitud, una dirección (ascendente o descendente) y una velocidad en la que la amplitud cambia (el periodo).

El portamento, es cuando el paso de una nota a otra, no es directo, sino que la frecuencia va cambiando progresivamente tocando todos los sonidos intermedios. Esto por ejemplo en una guitarra se hace cuando se arrastra el dedo sobre todos los trastes entre dos notas que se quieran tocar. En la GameBoy, este hardware de portamento, nos permite variar una nota con el tiempo, pudiendo definir un incremento o decremento de la frecuencia base con el tiempo, y cuanto cambia esta frecuencia.

Vamos a ver a continuación los registros del sistema de sonido y sus funciones:

Canal 1 - Tono y portamento

$FF10 - NR10 - Registro de portamento del canal 1(R/W)

Bit 6-4 - Duración del portamento
Bit 3   - Incremento/Decremento del portamento
           0: Adicción     (la frecuencia se incrementa)
           1: Sustracción (la frecuencia se decrementa)
Bit 2-0 - Paso actual del desplazamiento (n: 0-7)

Duración del portamento:

000: Apagado - sin cambios de frecuencia
001: 7.8 ms  (1/128Hz)
010: 15.6 ms (2/128Hz)
011: 23.4 ms (3/128Hz)
100: 31.3 ms (4/128Hz)
101: 39.1 ms (5/128Hz)
110: 46.9 ms (6/128Hz)
111: 54.7 ms (7/128Hz)

El cambio de la frecuencia original (definido en NR13,NR14) en cada paso, se calcula con la siguiente fórmula, donde X(0) es la frecuencia inicial y X(t-1) es la última frecuencia:

X(t) = X(t-1) +/- X(t-1)/2^n

$FF11 - NR11 - Canal 1 duración/ciclo de trabajo (R/W)

Bit 7-6 - Ciclo de trabajo (R/W)
Bit 5-0 - Longitud (R) (t1: 0-63)

Ciclo de trabajo:

00: 12.5% ( _-------_-------_------- )
01: 25%   ( __------__------__------ )
10: 50%   ( ____----____----____---- ) (normal)
11: 75%   ( ______--______--______-- )

Longitud = (64-t1)*(1/256) segundos La longitud solo se utiliza si el Bit 6 en NR14 está a uno.

$FF12 - NR12 - Canal 1 - Envolvente (R/W)

Bit 7-4 - Volumen inicial de la envolvente (0-0Fh) (0=Sin sonido)
Bit 3   - Dirección de la envolvente (0=Decrece, 1=Crece)
Bit 2-0 - Periodo (n: 0-7)
          (si es cero, la envolvente no actua.)

Longitud de un paso = n*(1/64) segundos

$FF13 - NR13 - Canal 1 - Frecuencia (low) (W)

8 bits bajos de los 11 bit de la frecuencia (x). Los siguientes 3 bits están en NR14 ($FF14)

$FF14 - NR14 - Canal 1 - Frecuencia (hi) (R/W)

Bit 7   - Disparador (1=Reinicia el sonido) (W)
Bit 6   - Activa o desactiva la longitud (R/W)
          (1=Detiene el sonido cuando alcanza la longitud en NR11)
Bit 2-0 - 3 bits altos de la frecuencia (x) (W)

Frecuencia = 131072/(2048-x) Hz

Canal 2 - Tono

Este canal funciona exactamente igual que el 1, pero no tiene un registro de portamento.

$FF16 - NR21 - Canal 2 Longitud/Ciclo de trabajo (R/W)

Bit 7-6 - Ciclo de trabajo (R/W)
Bit 5-0 - Longitud (R) (t1: 0-63)

Ciclo de trabajo:

00: 12.5% ( _-------_-------_------- )
01: 25%   ( __------__------__------ )
10: 50%   ( ____----____----____---- ) (normal)
11: 75%   ( ______--______--______-- )

Longitud = (64-t1)*(1/256) segundos La longitud solo se utiliza si el Bit 6 en NR14 está a uno.

$FF17 - NR22 - Canal 2 Envolvente (R/W)

Bit 7-4 - Volumen inicial de la envolvente (0-0Fh) (0=Sin sonido)
Bit 3   - Dirección de la envolvente (0=Decrece, 1=Crece)
Bit 2-0 - Periodo (n: 0-7)
          (si es cero, la envolvente no actua.)

Longitud de un paso = n*(1/64) segundos

$FF18 - NR23 - Canal 2 - Frecuencia (lo) (W)

8 bits bajos de los 11 bit de la frecuencia (x). Los siguientes 3 bits están en NR24 ($FF19)

$FF19 - NR24 - Canal 2 - Frecuencia (hi) (R/W)

Bit 7   - Disparador (1=Reinicia el sonido) (W)
Bit 6   - Activa o desactiva la longitud (R/W)
          (1=Detiene el sonido cuando alcanza la longitud en NR21)
Bit 2-0 - 3 bits altos de la frecuencia (x) (W)

Frecuencia = 131072/(2048-x) Hz

Canal 3 - Onda programable

Este canal se puede usar para reproducir sonido digital, pero la longitud del buffer de samples (RAM de onda) Está limitada a 32 valores de 4 Bits. Se podria usar este canal para sacar notas normales si inicicalizamos la memoria de onda con los valores de una onda cuadrada. No dispone de control de envolvente.

$FF1A - NR30 - Canal 3 on/off (R/W)

Bit 7 - Apaga o enciende el canal  (0=Detenido, 1=Reproduce)  (R/W)

$FF1B - NR31 - Canal 3 - Longitud

Bit 7-0 - Longitud (t1: 0 - 255)

Longitud = (256-t1)*(1/256) segundos. Este valor sólo se usa si el bit 6 de NR34 está a uno.

$FF1C - NR32 - Canal 3 - Nivel de salida (R/W)

Bit 6-5 - Seleccionar volumen de la salida (R/W)

Posibles valores son:

00: Apagado (sin sonido)
01: 100% Volumen (Datos de la RAM de onda tal cual)
10:  50% Volumen (Datos de la RAM de onda desplazados una vez a la derecha)
11:  25% Volumen (Datos de la RAM de onda desplazados dos veces a la derecha)

$FF1D - NR33 - Canal 3 - Frecuencia (lo) (W)

8 bits bajos de la frecuencia del canal(x).

$FF1E - NR34 - Canal 3 - Frecuencia (hi) (R/W)

Bit 7   - Disparador (1=Reinicia el sonido) (W)
Bit 6   - Activa o desactiva la longitud (R/W)
          (1=Detiene el sonido cuando alcanza la longitud en NR11)
Bit 2-0 - 3 bits altos de la frecuencia (x) (W)

Frecuencia = 131072/(2048-x) Hz

$FF30-$FF3F - Memoria de onda

Contiene los valores para la generación de la onda.

Esta memoria se organiza en 32 valores de 4 bit que se reproducen con los 4 bits altos en primer lugar.

Canal 4 - Ruido

Este canal se usa para reproducir ruido blanco. Esto se logra variando la amplitud aleatoriamente dada una frecuencia. Dependiendo de la frecuencia, el ruido parecerá más “duro” o “blando”.

También se puede influenciar la salida del generador de números aleatorios, permitiendo menos variación y asi una salida de tono casi normal.

$FF20 - NR41 - Canal 4 - Longitud (R/W)

Bit 5-0 - Longitud (R) (t1: 0-63)

Longitud = (64-t1)*(1/256) segundos La longitud solo se utiliza si el Bit 6 en NR44 está a uno.

$FF21 - NR42 - Canal 4 - Envolvente (R/W)

Bit 7-4 - Volumen inicial de la envolvente (0-0Fh) (0=Sin sonido)
Bit 3   - Dirección de la envolvente (0=Decrece, 1=Crece)
Bit 2-0 - Periodo (n: 0-7)
          (si es cero, la envolvente no actua.)

Longitud de un paso = n*(1/64) segundos

$FF22 - NR43 - Canal 4 - Contador polinómico (R/W)

La amplitud se cambia aleatoriamente entre alto y bajo a la frecuencia dada. Una frecuencia alta hará el ruido más “suave”. Cuando el bit 3 está a uno, la salida es más regular, y algunas frecuencias suenan más como tono que como ruido.

Bit 7-4 - Frecuencia del reloj de desplazamiento (s)
Bit 3   - Longitud del contador (0=15 bits, 1=7 bits)
Bit 2-0 - Radio de división de las frecuencias (r)

Frecuencia = 524288 Hz / r / 2^(s+1) ; Para r=0, se comporta como si r=0.5

$FF23 - NR44 - Channel 4 - Contador; Disparador (R/W)

Bit 7   - Disparador (1=Reinicia el sonido) (W)
Bit 6   - Activa o desactiva la longitud (R/W)
          (1=Detiene el sonido cuando alcanza la longitud en NR21)

Registros de control generales del sonido

$FF24 - NR50 - Control de volumen / 5º Canal (R/W)

Los bits de volumen controlan el Volumen principal de las salidas izquierda y derecha.

Bit 7   - Vin sale por SO2 (1=activado)
Bit 6-4 - Volumen de SO2 (0-7)
Bit 3   - Vin sale por SO1 (1=Activado)
Bit 2-0 - Volumen de SO1 (0-7)

La señal Vin viene del bus del cartucho, permitiendo a hardware externo en este, añadir un quinto canal a los cuatro internos de la GameBoy.

$FF25 - NR51 - Selección de salida de cada canal (R/W)

Nos permite enviar cada canal a la salida izquierda o derecha (o a ambas o ninguna).

Bit 7 - Canal 4 a la salida SO2
Bit 6 - Canal 3 a la salida SO2
Bit 5 - Canal 2 a la salida SO2 
Bit 4 - Canal 1 a la salida SO2
Bit 3 - Canal 4 a la salida SO1
Bit 2 - Canal 3 a la salida SO1
Bit 1 - Canal 2 a la salida SO1
Bit 0 - Canal 1 a la salida SO1

$FF26 - NR52 - Sonido Encendido/Apagado

Si tus programas de GameBoy no usan sonido, escribir 00h en este registro, te ahorrará un 16% o más de consumo eléctrico. Deshabilitar el sistema de sonido poniendo a cero el Bit 7 destruye el contenido de todos los registros de sonido. Además, deja inaccesibles todos estos registros (excepto el mismo $FF26) mientras el sistema de sonido esté apagado.

Bit 7 - Activa o desactiva todo el sonido  (0: Detener todos los circuitos de sonido) (R/W)
Bit 3 - Canal 4 ON (R)
Bit 2 - Canal 3 ON (R)
Bit 1 - Canal 2 ON (R)
Bit 0 - Canal 1 ON (R)

Los Bits 0-3 de este registro, son sólamente bits de estátus, escribir en ellos no activa o desactiva el sonido de esos canales. Estos flags se ponen a uno cuando se activa el flag “Disparador” del canal (Bit 7 en NR14-NR44), el flag permanece a uno mientras dure la longitud del sonido (si está activa). Una envolvente que ha hecho bajar la amplitud a cero, no desactivaria este flag.

tutorial_de_ensamblador_sonido.txt · Última modificación: 08/02/2017 21:21 (editor externo)