Posts Tagged ‘Música’

h1

El rey puede cantar

7 abril 2009

Es muy probable que Arduino de Ivrea disfrutara con la música y entra dentro de lo posible que alguna vez cantara. De lo que no tenemos duda es que el sistema Arduino puede “cantar”, eso ya lo hemos comprobado quienes tenemos uno. Basta con cargar el programa Melody que viene como ejemplo dentro del directorio Digital y conectar un zumbador piezoeléctrico en el puerto apropiado.

¿Y qué sucede cuando queremos programar nuestras propias melodías y tenemos conocimientos limitados en programación y nuestro solfeo se limita a poner con dificultad la escala musical en un pentagrama? No hay problema, tenemos gran parte del conocimento humano disponible desde casa, sólo nos hace falta un poco de entusiasmo y ganas para dar con la solución. Pongámonos un desafío: tocar el “Himno de la alegría“. En un principio pensé en la “Marcha imperial“, pero aún faltan unos años para que pase al dominio público. Aprovecho para pedir a los compositores que en lugar del poco solidario y asfixiante copyright, licencien su música bajo Creative Commons. De todos modos, gente con menos escrúpulos que yo ante las licencias ya han realizado esta melodía. En este vídeo podemos escucharlo.

Siguiendo con nuestro objetivo, trataremos de tocar las primeras notas, justo las que acompañan a los siguientes versos (desde este enlace es posible oirlo):

Escucha, hermano, la canción de la alegría,
el canto alegre del que espera un nuevo día.

Tras analizar el código fuente de Melody observo que cada una de las notas musicales se representa con un símbolo y se corresponde con una determinada frecuencia. En la siguiente tabla tenemos la equivalencia.

Nota Símbolo Frecuencia (Hz) Período (μs) Anchura del pulso(μs)
do c 261 3830 1915
re d 294 3400 1700
mi e 329 3038 1519
fa f 349 2864 1432
sol g 392 2550 1275
la a 440 2272 1136
si b 493 2028 1014
do C 523 1912 956

Tras indagar por la Red, compruebo que estos valores son bastante comunes y sólo encuentro ligeras diferencias, por lo que los doy por válidos. Mediante señales digitales y modulando su anchura de impulso, PWM, podemos conseguir las diferentes notas. Como sabemos, Arduino dispone de 14 puertos de salida digital de los cuales seis proporcionan PWM: 3, 5, 6, 9, 10, y 11.

Tomando como base Melody creo NotasMusicales, un programa que emite todas las notas anteriores en orden ascendente primero y descendente a continuación, que desde este enlace puede ser descargado. Seguidamente pasamos a describir su código.

// ****************DECLARACIÓN DE VARIABLES****************
int zumbadorPin = 11;
int N = 17;
char notas[] = "cdefgabCCbagfedc ";
int golpes[] = { 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 4 };
int tempo = 300;

  • zumbadorPin: puerto al que ha de conectarse el zumbador piezoeléctrico.
  • N: número de notas que contiene la melodía más uno.
  • notas[]: variable matricial con cada una de las notas de la melodía. Sería como la partitura de nuestra melodía. Debe terminar en un espacio en blanco, que será el símbolo utilizado para indicar que la melodía ha finalizado.
  • golpes[]: contiene los valores que, multiplicados por tempo, nos dará la duración de cada una de las notas. Debe tener tantos valores como el asignado a N.
  • tempo: constante que se utilizará para multiplicar los distintos valores que contenga golpes[] y obtener de este modo su tiempo.


void setup() {
pinMode(zumbadorPin, OUTPUT);
}
// ******************PROGRAMA PRINCIPAL******************
void loop() {
for (int i = 0; i < N; i++) {
if (notas[i] == ' ') {
delay(golpes[i] * tempo);
}
else {
tocarNota(notas[i], golpes[i] * tempo);
}
delay(tempo / 2);
}
}
Tras configurar zumbadorPin como salida, el programa principal consta de un bucle que se repetirá N+1 veces y que llamará N veces a la función tocarNota(x, y), con un valor de x igual a una de las notas de la partitura, y uno de y que será el resultado de multiplicar tempo, 300, por el valor asignado en golpes[] a la nota correspondiente. Al llegar al espacio en blanco, notas[i]==’  ‘, se hará un retardo de golpes[17]*tempo=1,2 s. Para finalizar se pone entre nota y nota un retardo de 0,15 s.

//*********************FUNCIONES***********************
void tocarNota(char nota, int duracion) {
char nombre[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
int tonos[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
for (int i = 0; i < 8; i++) {
if (nombre[i] == nota) {
tocarTono(tonos[i], duracion);
}
}
}
La función tocarNota(x, y) utiliza las variables matriciales nombre[] y tonos[] para asignar a cada nota su ancho de impulso. Mediante el bucle for se determina el valor de i que corresponde a la nota a tocar y se llama a la función tocarTono(u,v), con un valor de u igual al ancho de impulso de dicha nota y un valor v igua a y. Por ejemplo, si del programa principal se viene con i=2, la llamada viene como tocarNota(‘e’, 300) y se llama a tocarTono(1519, 300).

void tocarTono(int tono, int duracion) {
for (long i = 0; i < duracion * 1000L; i += tono * 2) {
digitalWrite(zumbadorPin, HIGH);
delayMicroseconds(tono);
digitalWrite(zumbadorPin, LOW);
delayMicroseconds(tono);
}
}
Esta función crea una señal cuyo semiperíodo corresponde con el valor del tono de la nota que se repetirá hasta que se alcance el valor de multiplicar por mil el contenido de duración. Por ejemplo: si del programa principal i=7 en la función tocarNota(), nota=notas[7]=’C’ y duracion=golpes[7] * tempo= 2*300=600. Al ejecutarse esta función y llamar a tocarTono(), se tiene que tono=tonos[7]=956 y duracion=600. El bucle se repetirá hasta alcanzar el valor duracion*1000L=600.000. Los valores i para el bucle serán 0, tono*2=1912, tono*4=3824, tono*6= 5736 … tono*2k. Esto hace que el bucle se repita un total de 314 veces, desde k=0 hasta K=313: tono*2*313=598456.  De este modo se consigue una señal con una frecuencia de 523 Hz sonando durante un tiempo de 314/523=0,6s.

Este programa podrá tomarse como base para obtener cómodamente otras melodías sencillas que puedan obtenerse con la escala de la tabla. Sólo habrá que asignar a las variables N, notas[] y golpes[] los valores adecuados de acuerdo con lo comentado. Tras encontrar fácilmente la partitura en la Red y pedir un poco de ayuda obtengo lo deseado.

himno-alegria

En total son 26 notas, y dando a las blancas un tiempo doble que a las negras, tenemos:

  • N=27
  • notas[] = “efggfedccdeedefggfedccdedc “
  • golpes[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 4}

Por lo tanto, objetivo cumplido. Aquí podemos oír a nuestro rey cantando de alegría descansado apaciblemente sobre una máquina GNU/Linux, cómo no.

Anuncios