En la entrada anterior hemos visto cómo guardar en una tabla la información de la melodía, es decir, la secuencia de notas con sus octavas. Si en vez de tener una melodía simple, tuviéramos una melodía con dos o tres voces, sería suficiente con que la tabla fuera de doble o triple entrada.
Además de lo anterior, hemos visto cómo leer la tabla, convertir la información de octavas y notas a frecuencias (consultando una tabla de frecuencias para la octava 7 y dividiendo la frecuencia obtenida por dos N veces), y cómo programar el SID con las frecuencias.
El esquema anterior (guardar la información musical en una tabla) se puede extender también a la duración de las notas y su volumen. De esto nos ocupamos en esta entrada.
La duración de las notas es el tiempo que transcurre desde que empieza la fase “attack” hasta que termina la fase “release”:
La fase “attack” empieza cuando se activa el bit 0 del registro VCREG1/2/3. La fase “release” empieza cuando se desactiva ese mismo bit 0, y termina tras la duración de esa fase (recuérdese que el parámetro “release” es un tiempo).
Por tanto, podemos controlar la duración de la nota controlando el tiempo desde que activamos el bit 0 del registro VCREG1/2/3 hasta que lo desactivamos. Esto se puede hacer con una rutina de retardo. Y la duración de cada nota se puede registrar en una nueva entrada de la tabla ya descrita anteriormente.
Sin ser experto en música, supongo que musicalmente no será necesario que las tres voces estén sincronizadas. Es decir, supongo que es perfectamente posible que una voz y otra cambien de nota en momentos diferentes. Sin embargo, desde el punto de vista de la programación, esto complicaría mucho el programa, y más en un ordenador como el C64 que sólo tiene un hilo de ejecución (interrupciones aparte).
Por todo ello, supondremos que las tres voces del C64 van sincronizadas, es decir, empiezan a la vez, y cambian de una nota a la siguiente en el mismo instante. O, lo que es lo mismo, las duraciones de las sucesivas notas tienen que ser las mismas para las tres voces.
En definitiva, será suficiente con añadir una cuarta columna a nuestra tabla de triple entrada, que ahora pasará a ser de cuádruple entrada:
La duración de las notas no se suele expresar en términos absolutos (por ejemplo, «una negra equivale a un segundo»). Más bien, se suele expresar como una proporción de un compás. De este modo, si el compás es de 4/4, las duraciones son:
- Redonda = 4/4
- Blanca = 2/4
- Negra = 1/4
- Corchea = 1/8
- Semicorchea = 1/16
- Fusa = 1/32
- Semifusa = 1/64
Desde el punto de vista de la programación, dado que vamos a usar una rutina de retardo para controlar la duración (básicamente un bucle), lo más práctico es que la rutina haga más o menos iteraciones en función del tipo de nota. Y puesto que nos interesa no complicar mucho más la tabla anterior, lo más práctico sería algo así:
- Redonda = 16 iteraciones.
- Blanca = 8 iteraciones.
- Negra = 4 iteraciones.
- Corchea = 2 iteraciones.
- Semicorchea = 1 iteración.
- Fusa = prescindir.
- Semifusa = prescindir.
De este modo, dedicando el nibble alto de la cuarta entrada a la duración es suficiente, y podemos dedicar el nibble bajo al volumen. Por tanto, tenemos que prescindir de fusas y semifusas en aras de mantener la tabla lo más sencilla posible.
Y con el volumen ya hemos dejado caer lo que va a pasar. El volumen es común para las tres voces (bits 0, 1, 2 y 3 del registro SIGVOL). Y sólo puede tomar los valores 0 – 15. Por tanto, perfectamente podemos almacenarlo en el nibble que deja libre la duración (nibble bajo).
En conclusión, si complicamos el programa de ejemplo de la entrada anterior, de modo que, además de las octavas y notas para las tres voces, también estén en la tabla (que pasa a tener cuatro entradas) la duración y el volumen, ya tenemos todo resuelto. Además de leer y configurar las frecuencias de las diferentes voces, tendremos que leer y configurar el volumen, y mantener las voces activas durante el tiempo indicado, cambiando entonces a la siguiente nota.
Un último apunte de interés es que, en cuanto las melodías tengan unas pocas notas, la tabla superará las 256 posiciones de memoria. Por tanto, es probable que el modo de direccionamiento indexado se nos quede corto, y tengamos que usar el modo de direccionamiento indirecto – indexado.
Programa de ejemplo: Prog53