# Generar melodías con PIC



## PICMIND (Ago 23, 2007)

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


----------



## aerodesliza (Ago 29, 2007)

Rcuerdo cuando realize ese proyecto pero en assembler, fue dificil pero funcionaba nitido, claro en MikroC y softwares similares se hace muy facilmente


----------



## pic-man (Ago 29, 2007)

Esto es muy interesante, yo tengo pensado hacerlo pero en assembler, uno de estos días comenzaré y cuando termine postearé el proyecto.


----------



## tiopepe123 (Ago 30, 2007)

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.


----------



## Francisco Galarza (Ago 30, 2007)

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:





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






Fuente: http://www.latecladeescape.com/w0/content/view/94/49/


----------



## pic-man (Ago 30, 2007)

Para quien quiera manejar más tonos funcionan muy bien las ecuaciones de Francisco Galarza, pero siempre es más fácil ver el valor de la frecuencia directamente de una lista   

Aquí están las frecuencias de las 88 teclas de un piano


----------



## sp_27 (Sep 8, 2007)

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
> ...



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.


----------



## ghost_007 (Sep 13, 2007)

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  _____|
                  |                                               |


----------



## ghost_007 (Sep 13, 2007)

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.


----------



## sp_27 (Sep 24, 2007)

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?


----------



## pepechip (May 2, 2008)

Hola
tengo una duda. 
¿Al implementar una partitura cualquiera hay que dejar algun tiempo sin ningun sonido entre una nota y la siguiente?


----------



## sp_27 (May 7, 2008)

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.


----------



## pepechip (May 7, 2008)

muchas gracias, pensaba que ya nadie me hiba a resolver la duda.


----------



## nerea185 (May 16, 2008)

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.


----------



## pepechip (May 16, 2008)

"problemas".
Es una palabra bastante generica, deves de ser mas concreto.


----------



## nerea185 (May 16, 2008)

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


----------



## pepechip (May 16, 2008)

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


----------



## lichi (Oct 25, 2012)

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


----------



## jhonjz (Mar 16, 2013)

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. 


```
#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);



}
}
```


----------



## sp_27 (Mar 16, 2013)

jhonjz dijo:


> 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.
> 
> 
> ```
> ...



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


----------



## jhonjz (Mar 16, 2013)

sp_27 dijo:


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



Sí, esa es una parte de la canción, de hecho la parte que sigue es una serie de notas simultáneas, eso es lo que quero programar en el C, ¿Cómo lo hago?


----------



## Chico3001 (Mar 16, 2013)

No puedes... al menos no si tu algoritmo no esta enfocado a generar polifonias, (algo como lo que paso con los primeros celulares que tocaban musica, tenias que bajar tonos monofonicos o polifonicos segun el modelo del celular)

Tienes que replantear el algoritmo completamente, para añadir rutinas que sumen las formas de onda de cada tono individual y generen una resultante que es la que se envia al amplificador


----------



## jeryus (Abr 9, 2013)

Chico3001 dijo:


> No puedes... al menos no si tu algoritmo no esta enfocado a generar polifonias, (algo como lo que paso con los primeros celulares que tocaban musica, tenias que bajar tonos monofonicos o polifonicos segun el modelo del celular)
> 
> Tienes que replantear el algoritmo completamente, para añadir rutinas que sumen las formas de onda de cada tono individual y generen una resultante que es la que se envia al amplificador



yo presento la misma duda del compañero, es decir, como hacer para que, en caso de que presione la tecla correspondiente a SOL, SI y RE me arroje por la bocina la respectiva armonia? menciono esos 3 tonos pero preguntaria lo mismo si fuera un caso de teclas al azar... sin embargo, no comprendo como hacer eso que mencionaste, habra alguna manera de que nos encamines un poco ? si no es molestia?


----------



## Chico3001 (Abr 10, 2013)

Al igual que ustedes siempre me salio la interrogante, solo que nunca me puse a hacer un ejercicio para resolverlo... 

La solucion que se me ocurrio es generando una base de tiempos estandar usando el timer e interrupciones, Durante cada interrupcion se evalua cada tono y se prende o se apaga un bit de cada puerto por cada tono, es decir si habra 8 tonos a tocar necesitaran 8 pines para cada uno

Luego con un OPAMP configurado como sumador podemos sumar la salida de cada uno de los pines y asi mandar la resultante a una bocina

La otra seria evaluar numericamente cada tono por tiempos y con eso mandar la salida a un DAC solo que requiere mas trabajo matematico del micro..


----------



## jeryus (Abr 10, 2013)

Chico3001 dijo:


> Al igual que ustedes siempre me salio la interrogante, solo que nunca me puse a hacer un ejercicio para resolverlo...
> 
> La solucion que se me ocurrio es generando una base de tiempos estandar usando el timer e interrupciones, Durante cada interrupcion se evalua cada tono y se prende o se apaga un bit de cada puerto por cada tono, es decir si habra 8 tonos a tocar necesitaran 8 pines para cada uno
> 
> ...



habia considerado tu respuesta del sumador pero en basic me atore con la interrogante de 

que la libreria/funcion(?) de Sonido me pide inicializarla a 1 puerto en especifico por ejemplo 

Sound_Init(PORTD, 3)    siendo el 4bit del puerto D
Sound_Play(880, 5000) y en este caso, solo envia la frecuencia de 880hz en un tiempo de 5 segundos, y solo se utiliza ese puerto en lo que corre del programa para diferentes frecuencias y diferentes salidas de sonido, solo que se envian uno a la vez...

hay manera de configurar varios puertos como salida de sonido, y segun lo que planteas, ocupare 8, un puerto de salida de sonido para cada uno de los tonos que mencionas... ? 

hay manera de configurar un puerto de salida de sonido exclusivo para cada "tono" de entrada ? es decir, si voy a tener 8 tonos de entrada mediante switches, tener 8 pines por los cuales van a salir las 8 respectivaas frecuencias... ?


----------



## nannasin28 (Abr 10, 2013)

fácil ver el valor de la frecuencia directamente de una lista..


----------



## Chico3001 (Abr 10, 2013)

https://www.forosdeelectronica.com/f24/pic-multiples-senales-pwm-69981/
https://www.forosdeelectronica.com/f13/obtener-mas-pwm-pic-16f877a-95121/
https://www.forosdeelectronica.com/f24/8-canales-pwm-16f628a-61488/
http://www.neoteo.com/8-canales-de-pwm-con-un-16f628a

Obvio hay limitantes... pero se puede ir haciendo de forma simple y poco a poco


----------



## soymoe (Ago 28, 2013)

Les dejo mis videos de reproducir melodias con PIC


----------

