Generar melodías con PIC

Hola a todos.

Bueno aquí estoy de nuevo con otro proyecto, esta vez voy a explicar como generar melodías con un PIC de forma super sencilla; primero voy a explicar algunas cosas que puedes obviar si sabes algo de música.

Las canciones que escuchamos están compuestas por notas musicales (DO, RE, MI, FA, SOL, LA, SI) a cada una de estas notas le corresponde una frecuencia. En la siguiente tabla mostraré qué frecuencia le corresponde a cada nota:

Do – C 262 Hz
Re – D 294 Hz
Mi – E 330 Hz
Fa – F 349 Hz
Sol – G 392 Hz
La – A 440 Hz
Si - B 494 Hz

Las letras que coloqué al lado de cada nota pertenecen a la nomenclatura inglesa (otra forma de llamar a las notas), las coloqué por que son con las que trabaja la librería del PIC C Compiler.

Las notas tienen también una duración, que está determinada por las figuras musicales; para este ejemplo se usará la siguiente duración.

Fusa 62 mS
Semicorchea 125 mS
Corchea 250 mS
Negra 500 mS
Blanca 1 Segundo
Redonda 2 Segundos

No se si estos tiempos son los correctos, pero las melodías con la que los he probado suenan bien, si alguna sabe con exactitud la duración de la figuras por favor corríjanme.

Bueno ya tenemos la frecuencia y la duración, entonces a explicar el código. Las notas se generarán utilizando una librería que trae el CCS. La librería de llama “TONES.C” e incluye esta función:

generate_tone(frequency, duration)

Esta función nos permitirá crear las notas musicales. Para usarla debemos tener en cuenta los siguientes parámetros:

“frecuency” es una variable que tomará el valor de la nota que queramos generar.
“duration” es el tiempo que durará la nota y está dada en milisegundos.

La librería trae predefinidas las frecuencias adecuadas para cada nota y permite elegir en que octava tocarla; permite hasta una tercera octava. A continuación les mostraré las tablas:

// NOTE FREQUENCY
// Octave0 Octave1 Octave2 Octave3
const long C_NOTE[4] ={ 262, 523, 1047, 2093};
const long Db_NOTE[4] ={ 277, 554, 1109, 2217};
const long D_NOTE[4] ={ 294, 587, 1175, 2349};
const long Eb_NOTE[4] ={ 311, 622, 1245, 2489};
const long E_NOTE[4] ={ 330, 659, 1329, 2637};
const long F_NOTE[4] ={ 349, 698, 1397, 2794};
const long Gb_NOTE[4] ={ 370, 740, 1480, 2960};
const long G_NOTE[4] ={ 392, 784, 1568, 3136};
const long Ab_NOTE[4] ={ 415, 831, 1661, 3322};
const long A_NOTE[4] ={ 440, 880, 1760, 3520};
const long Bb_NOTE[4] ={ 466, 923, 1865, 3729};
const long B_NOTE[4] ={ 494, 988, 1976, 3951};

OJO: Esto solo lo coloco como una ayuda por si alguien está perdido, no es la librería completa, es solo un pedazo, si la copian así, nunca les va a funcionar.

Así pues, si por ejemplo queremos generar un Do que dura una negra, le decimos entonces:

generate_tone(C_NOTE[0], 500);

Entonces si queremos generar la escala musical, sería así:

generate_tone(C_NOTE[0], 500);
generate_tone(D_NOTE[0], 500);
generate_tone(E_NOTE[0], 500);
generate_tone(F_NOTE[0], 500);
generate_tone(G_NOTE[0], 500);
generate_tone(A_NOTE[0], 500);
generate_tone(B_NOTE[0], 500);

Entonces teniendo esto y espero que todo haya quedado claro, lo único que necesitamos son las partituras de las canciones que queramos crear.

En el siguiente enlace encontrarán el código para tocar el "homino de la Alegría".

http://www.freewebs.com/picmind/melodiasconpic.htm
 
Rcuerdo cuando realize ese proyecto pero en assembler, fue dificil pero funcionaba nitido, claro en MikroC y softwares similares se hace muy facilmente
 
Ahora solo hace falta el midi, pero es muy facil, sobretodo en C.
Una solucion para tener el micro libre es utilizar el PWM o el CCP en modo especial, pero es necesario utilizar interrupciones.
 
Faltan las frecuencias de las notas sostenidas o bemoles:

C....Do.......261,63
C#..Do#....277,18 (Db)
D....Re.......293,66
D#..Re#....311,13 (Eb)
E.....Mi.......329,63
F.....Fa.......349,23
F#...Fa#....369,99 (Gb)
G....Sol.......392,00
G#..Sol#....415,30 (Ab)
A.....La.......440,00
A#...La#....466,16 (Bb)
B.....Si........493,88

Si querés tocar una misma nota más grave o más aguda podés cambiarla de octava. Para subir o bajar una octava se multiplica o se divide la frecuencia por dos. Ejemplo:
1760Hz-> A5
880Hz---> A4
440Hz---> A3
220Hz---> A2
110Hz---> A1

Esta fórmula nos permite calcular la frecuencia de cada nota:
image003.png

Donde
o: octava
n: número de nota (1 es Do, 2 es Do#...)
Esta es una deducción para usar potencias de e:
image005.png



Fuente: http://www.latecladeescape.com/w0/content/view/94/49/
 
PICMIND dijo:
Las notas tienen también una duración, que está determinada por las figuras musicales; para este ejemplo se usará la siguiente duración.

Fusa 62 mS
Semicorchea 125 mS
Corchea 250 mS
Negra 500 mS
Blanca 1 Segundo
Redonda 2 Segundos

No se si estos tiempos son los correctos, pero las melodías con la que los he probado suenan bien, si alguna sabe con exactitud la duración de la figuras por favor corríjanme.

He leido lo que han escrito todos y este proyecto me parece muy interesante, quisiera montarlo pero conozco poco de lenguaje emsamblador y espero no se me haga difícil, en cuando a los tiempos que dio PICMIND dependen de la referencia, pues para leer la música hay muchas reglas, como en la ortografía y gramática española, es un idioma.
Lo importante es que cada nota dura la mitad de la anterior, es decir, la semifusa dura la mitad de la fusa, esta dura la mitad de la semicorchea, esta a su vez dura la mitad de la corchea, y así hasta llegar a la redonda, pero todo depende del indicador del compás y del tiempo.
El indicador de compás es un número fraccionario que se coloca al inicio de una obra escrita (y a veces en el transcurso se cambia), el denominador indica cual nota se establece como unidad del tiempo y el numerador indica la cantidad de veces que esa nota cabe en un compás, ejemplo, un indicador de 3/4 indica que habrá 3 negras en un compás.
Denominadores: 1-redonda, 2- blanca, 4-negra, 8-corchea, 16-semicorchea, 32- fusa, 64-semifusa. Un compás es lo que está escrito entre dos líneas verticales.
Lo que los músicos llaman "tiempo", es la velocidad de la obra, se mide en pulsos por minuto y cada pulso corresponde a la nota establecida como unidad de tiempo.

Ejemplo: 3/4 en un allegro a 120: cada compás tendrá tres negras y en un minuto deben tocarse 120 negras, por lo tanto cada negra durará 500mS; si el indicador de compás es 3/8 y el tiempo es 120, un compás tendrá 3 corcheas y cada una durará 500mS; en un 3/4 en un lento a 60, cada negra durará 1 segundo, en un 3/8 presto a 150 cada corchea durará 400 mS; en un 4/4 a 100 el compás tendrá 4 negras y cada una durará 600mS. Por eso todo depende de la referencia.
 
hola tengo una duda con respecto a los tonos para generarlos, cuanto tiene que durar el pulso, por ejemplopara la nota DO el periodo dura dura 3.8 milisegundos (F=1/T, T=1/F y T=1/262), pero el tiempo de encendido ¿cuanto tiene que durar?

por ejemplo estas dos señales tienen la misma frecuencia pero distinta duracion del tiempo de encendido.
_____ ______
| | toff | | toff
_________| ton |__________________| ton |_________________

|____ 3.8 milisegundos _____|
| |


_________ _________
| | toff | | toff
_________| ton |______________| ton |______________

|____ 3.8 milisegundos _____|
| |
 
hola encontré lo que necesitaba y por si alguien tiene la misma duda que yo aquí dejo una tabla que indica los valores de ton.
 

Adjuntos

  • tab02g_194.gif
    tab02g_194.gif
    57.6 KB · Visitas: 1,103
Última edición por un moderador:
Hola a todos de nuevo, estuve revisando la página web donde están los proyectos propuestos por PICMIND pues estoy interesada en montar el que genera el Himno a la alegría usando otra canción, pero noté que el programa contiene un include que llama a un "TONES.C", revise en un computador y no conseguí dicha librería y en la página web el link que muestran no abre

[b dijo:
http://www.freewebs.com/picmind/proyectos.htm#126515150[/b]]A continuación les mostraré el código para que el PIC toque una canción, en este caso el “Himno de la alegría”, para esto utilicé la libreria del PIC C Compiler "TONES.C", para una mejor sigan este link: ...
Quisiera saber si me pueden ayudar con este problema, quisiera usar este programa para probar con otra canción, quizá otra menos conocida pero que me gusta mucho.

Gracias de antemano.

PD:¿PIC C Compiler es un programa?
 
Solamente si la partitura lo indica, deben dejarse algun tiempo sin sonido, si no lo indica, las notas suenan una luego de otra (salvo algunas excepciones).
La musica es un lenguaje, tiene simbolos para todo, te lo digo por experiencia, pase años estudiandola.
 
Hola!

Tengo que realizar un organo musical con el PIC16F874, y estoy teniendo problemas a la hora de meter las señales al PIC para las diferentes frecuencias. Si alguien pudiera ayudarme lo agradecería

Saludos.
 
Lo primero, gracias por contestar y preocuparte. la cosa es que soy nueva en esto de los PICs y no se como hacer el programa para meter las señales de audio, con sus frecuencias en el microcontrolador. si me podrias ayudar con alguna pauta te lo agradeceria. muchas gracias
 
Primeramente sabras que cada nota musical corresponde a una frecuencia determinada. (si no las tienes, las pides y las subo aqui)
Cada frecuencia le corresponde un periodo. P=1/F.
Como el periodo es el tiempo que transcurre desde que la salida vale 1 hasta que vuelve otra vez a tener el mismo valor, tu deveras de coger el Periodo obtenido y dividirlo entre 2, para asi tener el tiempo que la salida tiene que estar en on y en off.

ejemplo: la nota LA corresponde a la frecuencia de 440Hz. Por lo que el periodo sera 1/440=0,0022727 seg.
Por lo tanto la salida del micro devera de estar 1136useg en ON y otros 1136 useg en OFF. Y este proceso repetirlo durante todo el tiempo que tengas pisada esa tecla.

Precisamente hoy acaban de subir al foro un programa para calcular los retardos

https://www.forosdeelectronica.com/f24/generar-1-minute-pic-16f628a-14169/#post87168
 
Hola a todxs, quería hacer una consulta,
estoy programando un pequeño instrumento musical en ccs para pic16f84a.
la idea es que al presionar un botón ocurran una serie de sonidos
supongamos:

if (input(PIN_a0)==1){
GENERATE_TONE((a_note[0]),330);
delay_ms(330);
GENERATE_TONE((a_note[0]),330);
}

usando la biblioteca para generar tonos de onda cuadrada del ccs.

ahora bien, como estoy haciendo una serie de sonidos más larga, me interesaría lograr lo siguiente:

que SOLAMENTE se ejecute la función mientras está apretado el botón, es decir, supongamos que la orden es: sí el pin a0 es positivo, toca la-do-mi-sol-si-re-fa. pero que si suelto el pulsador a mitad de la orden se interrumpa su ejecución

espero haber sido claro con la duda.

Este foro es genial, estoy aprendiendo muchísimo.
desde ya muchas gracias a todxs por sus aportes!
salud
 
Hola, está muy bueno esto que plantean en el foro, soy amante de la música, toco piano, por lo que me ha sido muy fácil generar ya una melodía, estoy precisamente generando una melodía sencilla de Ave María, sin embargo, me encuentro en un punto donde tengo que hacer sonar dos notas a la misma vez, ¿Qué patrón debo seguir para lograr esto? Espero su ayuda y este es el código que parcialmente llevo por si lo quereís ensayar. La simulación es el mismo montaje que plante el amigo que inició con el foro.

Código:
#use delay (clock=4000000, RESTART_WDT)
#include <TONES.c>

int S_corchea=125,corchea=250,fusa=62;
long negra=500,blanca=1000,redonda=2000;

 

main()

{
set_tris_a(0x00);
set_tris_b(0x00);
output_b(0x00);
while (1)

{
generate_tone(C_NOTE[1], redonda);
generate_tone(E_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[2], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(E_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[2], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(D_NOTE[1], redonda);  
generate_tone(F_NOTE[1], redonda);
generate_tone(A_NOTE[1], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(D_NOTE[1], redonda);  
generate_tone(F_NOTE[1], redonda);
generate_tone(A_NOTE[1], redonda);
generate_tone(B_NOTE[0], redonda);
generate_tone(D_NOTE[1], redonda);
generate_tone(F_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(B_NOTE[0], redonda);
generate_tone(D_NOTE[1], redonda);
generate_tone(F_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(E_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[2], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(E_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[2], redonda);



}
}
 
Última edición por un moderador:
Hola, está muy bueno esto que plantean en el foro, soy amante de la música, toco piano, por lo que me ha sido muy fácil generar ya una melodía, estoy precisamente generando una melodía sencilla de Ave María, sin embargo, me encuentro en un punto donde tengo que hacer sonar dos notas a la misma vez, ¿Qué patrón debo seguir para lograr esto? Espero su ayuda y este es el código que parcialmente llevo por si lo quereís ensayar. La simulación es el mismo montaje que plante el amigo que inició con el foro.

Código:
#use delay (clock=4000000, RESTART_WDT)
#include <TONES.c>

int S_corchea=125,corchea=250,fusa=62;
long negra=500,blanca=1000,redonda=2000;

 

main()

{
set_tris_a(0x00);
set_tris_b(0x00);
output_b(0x00);
while (1)

{
generate_tone(C_NOTE[1], redonda);
generate_tone(E_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[2], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(E_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[2], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(D_NOTE[1], redonda);  
generate_tone(F_NOTE[1], redonda);
generate_tone(A_NOTE[1], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(D_NOTE[1], redonda);  
generate_tone(F_NOTE[1], redonda);
generate_tone(A_NOTE[1], redonda);
generate_tone(B_NOTE[0], redonda);
generate_tone(D_NOTE[1], redonda);
generate_tone(F_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(B_NOTE[0], redonda);
generate_tone(D_NOTE[1], redonda);
generate_tone(F_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(E_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[2], redonda);
generate_tone(C_NOTE[1], redonda);
generate_tone(E_NOTE[1], redonda);
generate_tone(G_NOTE[1], redonda);
generate_tone(C_NOTE[2], redonda);



}
}

¿Esto es lo que quieres hacer?
(revisar adjuntos)
 

Adjuntos

  • Ave Maria.rar
    11.9 KB · Visitas: 164
Atrás
Arriba