TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: septiembre_negro en 13 de Octubre de 2009, 23:17:04
-
Hola pues eso resulta que ya encaminados así el fin de año me ha entrado la ilusión de hacer cantar a un pic tonos navideños. Dándome una vuelta por el foro resulta que lo más fácil es utilizar la librería tones.c . Según leo esta librería ya tiene las notas musicales aquí viene la pregunta ¿como obtengo las notas de la melodía que quiero que mi pic interprete magistralmente?
Lo mas obvio es leer la partitura de la melodía pero (siempre hay uno) no tengo ni la mas jodida idea de cómo interpretarla.
Abra algún programa que me genere el do re mi fa si do
Como siempre agradezco sus comentarios
-
Hola.
Como asi que te genere?
Si tienes la partitura, posteala y yo te la paso a las notas, eso no es complicado.
-
Hola
Me explico mejor al estar investigando como hacer cantar al pic resulta que lo que hacen es leer directamente la partitura (me imagino que son estas personas que tienen conocimientos de música).
Si no recuerdo mal creo haber leído que existen programas a los cuales se les da a procesar la melodía en formato midi y este entrega las notas en un formato de texto que es de fácil lectura algo así por poner un ejemplo(do re mi fa sol).
O definitivamente no hay mas que interpretar directamente la partitura de la melodía ¿?
Ahora con respecto a tu amable ofrecimiento cualquier melodía me vienen para probar
Un saludo
A esto es alo que me refiero existe algún sof que genere algo parecido
La canción está armonizada a dos voces (SEXTAS)
A
El ca---mi--no que lle-va-a Be-lén
la si do# do# do# re do# re do#
mi sol# la la la si la si la
ba-jahas tael va--lle que la nie-ve cu-brió
la la si do# do# do# do# do# re do# re do#
mi mi sol# la la la la la si la si la
E
los pas-tor-ci--llos quie-ren ver a su rey
si do# re mi mi mi fa# mi re do# si
sol# la si do# do# do# re do# si la sol#
A D
le traen re-gal-os en suhu mil-de zu--rrón
si do# re mi mi mi fa# sol fa# mi re
sol# la si do# do# do# re mi re do# si
A E
ro pom pom pom, ro pom pom pom,
fa# mi re do# mi re do# si
re do# si la do# si la sol#
A
ha na---ci--doen un por-tal de Be-lén, el ni-ño Dios.
la si do# do# do# do# re do# re do# si la si la
mi sol# la la la la si la si la sol# mi sol# mi
A
Yo qui--sie--ra po--ner a tus pies
la si do# do# do# re do# re do#
mi sol# la la la si la si la
al-gún pre-sen--te que tea gra-de se-ñor
la la si do# do# do# do# re do# re do#
mi mi sol# la la la la si la si la
E
más tu ya sa--bes que soy po--bre tam-bién
si do# re mi mi mi fa# mi re do# si
sol# la si do# do# do# re do# si la sol#
A D
y no po-seo más queun vie-jo tam-bor
si do# re mi mi fa# sol fa# mi re
sol# la si do# do# re mi re do# si
A E
ro pom pom pom, ro pom pom pom,
fa# mi re do# mi re do# si
re do# si la do# si la sol#
A
en tuho-nor fren-teal por-tal to--ca-ré, con mi tam--bor.
la si do# do# do# do# re do# re do# si la si la
mi sol# la la la la si la si la sol# mi sol# mi
A
El ca---mi--no que lle-va-a Be-lén
la si do# do# do# re do# re do#
mi sol# la la la si la si la
yo voy mar--chan-do con mi vie-jo tam-bor
la la si do# do# do# do# re do# re do#
mi mi sol# la la la la si la si la
E
na---da me-jor hay que te pue-dao fre-cer
si do# re mi mi mi fa# mi re do# si
sol# la si do# do# do# re do# si la sol#
A D
su ron-coa cen-to es un can-to dea mor
si do# re mi mi mi fa# sol fa# mi re
sol# la si do# do# do# re mi re do# si
A E
ro pom pom pom, ro pom pom pom,
fa# mi re do# mi re do# si
re do# si la do# si la sol#
A
cua-ndo Dios me vio to--can-doan te él, me son-ri---ó.
la si do# do# do# do# re do# re do# si la si la
mi sol# la la la la si la si la sol# mi sol# mi
-
Hola.
En una partitura es importante también la duración de las notas, es decir el tempo musical.
Para que identifique la nota de una tablatura es mas bien sencillo, ya que las notas se identifican con una letra:
A : La
B : Si
C : Do
D : Re
E : Mi
F : Fa
G : Sol
Para el sostenido se usa el símbolo # y para el bemol se usa una b después de la nota. El # indica que se sube un semitono y el b que se baja un semitono, estos símbolos aparecen si se cambia la armadura de clave, es decir la base tonal de toda la canción.
Yo no conozco ningún software que haga eso, normalmente los hay pero al revés, es decir, que uno escriba la nota y que te genere el sonido.
Si tienes la partitura completa seria mejor, ya que de caso contrario, la melodia te va a sonar si ninguna base temporal.
Saludos
-
lo mas facil es grabar el audio en una eeprom, pero bueno, si queres hacerlo con pic te va a ser mas trabajoso...
yo usaria los ccp como generadores de tono (quizas los filtraria para sacar armonicos). lo que dicen mas arriba es cierto, no solo importa la nota sino tambien la duracion, que deberias controlarla con alguno de los timer.
los valores de frecuencia deben andar por algun lado, sino lo mas facil es agarrar la calculadora :P
A5 son 440hz
partiendo de eso solo tenes q multiplicar 440 por la raiz doceava de dos (no se como escribirlo)
eso te da 443 (o algo asi, no recuerdo), eso es A#5 (la sostenido)
si ese valor lo multiplicas de nuevo por la raiz doceava de 2 tenes B5, y asi sucesivamente tenes las 12 notas.
configura los ccp para generar dichas frecuencias.
despues tenes q hacer una especie de secuenciador que en cada negra decida si toca o no la nota correspondiente.
se puede hacer, pero no es sencillo (por lo menos para mis conocimientos basicos)
en todo lo que sea musical te puedo dar una mano, en la programacion hay gente q sabe mucho mas que yo...
-
Hola.
En una partitura es importante también la duración de las notas, es decir el tempo musical.
Si ahora mismo acabo de darme cuenta de eso aparte de la nota requiero el tiempo que se debe sostener la misma. Es increíble que después de un buen rato no encuentre la vendita partitura completa.
Ahora declarando que soy un completo ignorante en este tema da igual si la partitura es para piano violín flauta guitarra etc.
-
lo mas facil es grabar el audio en una eeprom, pero bueno, si queres hacerlo con pic te va a ser mas trabajoso...
Pues no no estoy casado con alguna forma en particular de hacerlo, comencé con esto por que no encontré otra forma de desarrollarlo. me encantaría si tienes tiempo de exponer como seria el proceso de grabar la melodía en una eeprom :-/ :-/
-
Por cristo resucitado como se lee esto :? :? :? :? :? :? :? :? :? :? :?
EL BURRITO DE BELÉN
e||-----------------|------------------|--1-----1-1---1--|--------------0-|
B||--------1-1---1--|--1---1---1---1---|-----------------|-3---3---1--3---|
G||*----------------|------------------|-----------------|----------------|
D||*----------------|------------------|-----------------|----------------|
A||-----------------|------------------|-----------------|----------------|
E||----3------------|------------------|-----------------|----------------|
e|-----------------|-------------------|--1-----1-1---1--|--------------0-|
B|----1---1-1---1--|---1---1-------1---|-----------------|-3---3---1--3---|
G|-----------------|-----------2-------|-----------------|----------------|
D|-----------------|-------------------|-----------------|----------------|
A|-----------------|-------------------|-----------------|----------------|
E|-----------------|-------------------|-----------------|----------------|
e|------------------|------------------|----------0---0--|----------------|
B|-------1---1---1--|--1---------1---1-|--1--------------|-3---3---1--0-1-|
G|------------------|------------------|-----------------|----------------|
D|------------------|------------------|-----------------|----------------|
A|------------------|------------------|-----------------|----------------|
E|------------------|------------------|-----------------|----------------|
________________
|1-2
e|------------------|------------------|----------0---0--|----------------|-----------------||
B|-----------1---1--|--1---------1---1-|--1--------------|-3---3---1--0-1-|-------1-1---1---||
G|------------------|------------------|-----------------|----------------|----------------*||
D|------------------|------------------|-----------------|----------------|----------------*||
A|------------------|------------------|-----------------|----------------|-----------------||
E|------------------|------------------|-----------------|----------------|-----------------||
________________
|3
e|-----------------|--0---0-0--0-0-------|-----------------|-0---0-0-----0------|
B|----1------------|----------------3-3--|--1---1----------|----------------3-3-|
G|-----------------|---------------------|-----------------|--------------------|
D|-----------------|---------------------|-----------------|--------------------|
A|-----------------|---------------------|-----------------|--------------------|
E|-----------------|---------------------|-----------------|--------------------|
e|------------------|------------------|-----------------|----------------|-------------|
B|---1-----3---3----|--3---3---3---3---|--0---0---3---3--|-3---1---0------|-------------|
G|------------------|------------------|-----------------|-------------2--|--0----------|
D|------------------|------------------|-----------------|----------------|-------------|
A|------------------|------------------|-----------------|----------------|-------------|
E|------------------|------------------|-----------------|----------------|-------------|
e|---0---0-0--0-0------|------------------|-0---0-0--0-0------|----------------|
B|-----------------3-3-|--1------------1--|---------------3-3-|-1-----1---1----|
G|---------------------|------------------|-------------------|----------------|
D|---------------------|------------------|-------------------|----------------|
A|---------------------|------------------|-------------------|----------------|
E|---------------------|------------------|-------------------|----------------|
e|------------------|--0----------------|-----------------|----------------||
B|----1---1---1---1-|------1-------3----|-3---1---0---3---|-1-----1-1---1--||
G|------------------|----------0--------|-----------------|----------------||
D|------------------|-------------------|-----------------|----------------||
A|------------------|-------------------|-----------------|----------------||
E|------------------|-------------------|-----------------|----------------||
-
Hola.
Eso es una tablatura para guitarra, el numero que se encuentra en la respectiva cuerda indica el traste que se debe "pisar" para obtener la nota. Si aparece el 0, es porque la cuerda va al aire. El orden de las cuerdas es
e=1 cuerda de abajo hacia arriba (nota Mi)
B=2 cuerda de abajo hacia arriba (nota Si)
... etc
No te recomiendo las tablaturas como esa, es mejor la partitura, ya que tiene mucha mas información, como la armadura de clave, los tempos de las notas, etc.
Respecto a la notación, hay que tener cuidado, si encuentras A5, denota un acorde no una nota, por lo que implica varias notas, por eso es importante la partitura, es mas descriptiva en todos los sentidos.
Saludos
-
OK te agradezco mucho la pagina donde lo baje según era para piano , me había resistido a hacerlo pero no va quedar mas que aprender música :? al menos lo suficiente para interpretar el código de las partituras .haber si no resulta que canto yo primero que el microcontrolador :D :D :D :D
-
El único riesgo que existe es que te guste tanto que no lo quieras dejar jamás .... a mi me paso!!!
Busca con la mulita el Guitar Pro, es un buen soft que te permite trabajar con partituras o tablaturas y acepta MIDI.
Saludos
-
perdon por el offtopic pero no me pude contener :mrgreen: :D :D :D :D
.haber si no resulta que canto yo primero que el microcontrolador :D :D :D :D
-
antes que nada, busca el midi: si no sabes musica, te vas a volver loco con partituras o tablaturas.
despues lo reproducis con aimp2 o winamp o alguno que te deje grabar en un archivo la salida de audio.
despues con algun editor de audio (soundforge o similar) tener que adecuar ese audio a la memoria en la que lo vas a grabar.
por ejemplo yo uso mucho las 27c040, que son eeprom de 512k x 8bits. creo que para una simple melodia esta mas que bien.
te dejo un link, yo saque de aca el metodo: wav to eeprom (http://web.telia.com/~u85920178/eprom/wave_00.htm)
perdon por la deschavada de pianista, cuando decia A5 me referia al A que esta sobre el C central, no al acorde [A-E] :P
-
OK les agradezco a todos ya veré que sale a un tengo tiempo también existe otro método que es utilizar el código rtttl utilizado por nokia para los RingTone
-
Pensé que eso era justamente lo que querías lograr :?, ese codigo define la nota con una letra, la duración temporal con un numero y la octava con otro numero, de esa manera queda fácil interpretar la melodía leyendo una cadena de caracteres.
Saludos
-
Pues si gusto eso es lo que pretendo el código rtttl lo recién lo descubrir pero sigo sin aclararme es posible utilizar este código como referencia para implementarlo con la librería notes del ccs. Me explico
Esto es un código rttl Simpsons:d=4,o=5,b=160:32p,c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g
Como quedaría si es posible utilizando la librería notes de ccs??
Ahora lo obvio seria utilizar directamente el código rtttl en el pic pero para mi desgracia el ejemplo que encontré utiliza una lógica muy avanzada y lo único que e conseguido es un tremendo dolor de cabeza ya ni siquiera pretendo entenderlo por ahora .
Si esta en la capacidad de alguien entender este ejemplo que habría que hacer para introducir mas melodías, modificar las que ya tiene no implica problema se sustituye el código actual por el de la melodía a y ya estampero lo que pretendo es meter tantas melodías como lo permita la memoria del pic.
Aquí una breve descripción del código rttl
http://personal.telefonica.terra.es/web/japus/rtplayer_es.html
Y aquí el programa que encontré en los foros del ccs para incrementar el código rtttl desafortunadamente para mi como principiante esta mas que en chino
/* */
/* RTTTL Ring Tone Player for Microchip Microcontrollers */
/* */
/* This program was designed to run on the PICDEM2 Plus demo board from */
/* Microchip. */
/* */
/* Usage: */
/* S3 - Selects Melody */
/* S2 - Starts/Stops Melody */
/* */
/* This code was designed for a clock speed of 20MHz */
/* The target device was a PIC18F452. */
/* You can use the PIC16F877 by changing the setup of CCP1 to */
/* CCP_COMPARE_INT. You will also need to toggle the output pin in the */
/* CCP1 interrupt routine. */
/* */
/* Many of the tunes were downloaded from "www.mrtones.com" */
/*****************************************************************************/
#case
#list
#if defined(__PCH__)
#include "18F452.h"
#else
#include "16F876.h"
#endif
#device *=16
#define CLOCKSPEED 10000000
#define CCP_COMPARE_TOGGLE_MATCH 2
#use delay(CLOCK=CLOCKSPEED)
#fuses HS, NOWDT, NOLVP, PUT
#define TMR1_PRESCALE 8
#define NOTE_C_SHARP (((CLOCKSPEED/4)/277.18)/TMR1_PRESCALE) // 277.18Hz
#define NOTE_D_SHARP (((CLOCKSPEED/4)/311.13)/TMR1_PRESCALE) // 311.13 Hz
#define NOTE_F_SHARP (((CLOCKSPEED/4)/369.99)/TMR1_PRESCALE) // 369.99 Hz
#define NOTE_G_SHARP (((CLOCKSPEED/4)/415.30)/TMR1_PRESCALE) // 415.30 Hz
#define NOTE_A_SHARP (((CLOCKSPEED/4)/466.16)/TMR1_PRESCALE) // 466.16 Hz
#define NOTE_C (((CLOCKSPEED/4)/261.63)/TMR1_PRESCALE) // 261.63 Hz
#define NOTE_D (((CLOCKSPEED/4)/293.66)/TMR1_PRESCALE) // 293.66 Hz
#define NOTE_E (((CLOCKSPEED/4)/329.63)/TMR1_PRESCALE) // 329.63 Hz
#define NOTE_F (((CLOCKSPEED/4)/349.23)/TMR1_PRESCALE) // 349.23 Hz
#define NOTE_G (((CLOCKSPEED/4)/392.00)/TMR1_PRESCALE) // 392.00 Hz
#define NOTE_A (((CLOCKSPEED/4)/440.00)/TMR1_PRESCALE) // 440.00 Hz
#define NOTE_B (((CLOCKSPEED/4)/493.88)/TMR1_PRESCALE) // 493.88 Hz
#define NOTE_SILENCE 0
#define DURATION_32 5 // Duration = 2^x
#define DURATION_16 4 // Duration = 2^x
#define DURATION_8 3 // Duration = 2^x
#define DURATION_4 2 // Duration = 2^x
#define DURATION_2 1 // Duration = 2^x
#define DURATION_1 0 // Duration = 2^x
typedef enum
{
SILENTNIGHT,
JINGLEBELLS,
LAST_MELODY
}MELODIES;
typedef struct
{
int Head;
int Tail;
int Count;
} NOTESTAT;
typedef struct
{
long note;
long duration;
}NOTE_DEF;
struct
{
int TRISC0:1;
int TRISC1:1;
int TRISC2:1;
int TRISC3:1;
int TRISC4:1;
int TRISC5:1;
int TRISC6:1;
int TRISC7:1;
}TRISCbits;
#if defined(__PCH__)
#locate TRISCbits = 0xF94
#else
#locate TRISCbits = 0x87
#endif
long TMR1;
#if defined(__PCH__)
#locate TMR1 = 0xFCE
#else
#locate TMR1 = 0x0E
#endif
int TMR1L;
#if defined(__PCH__)
#locate TMR1L = 0xFCE
#else
#locate TMR1L = 0x0E
#endif
int TMR1H;
#if defined(__PCH__)
#locate TMR1H = 0xFCF
#else
#locate TMR1H = 0x0F
#endif
int TMR0;
#if defined(__PCH__)
#locate TMR0 = 0xFD6
#else
#locate TMR0 = 0x01
#endif
#define MAX_NOTE_BUFFER_SIZE 4
#define NOTE_ROLLOVER_MASK 0b00000011
NOTE_DEF NoteBuffer[MAX_NOTE_BUFFER_SIZE];
NOTESTAT Notestat = {0,0,0};
long DurationCount=0;
int Tempo=0;
long Note_Ticks=0;
MELODIES Melody_Pointer;
long Note_Index = 0xFFFF;
BOOLEAN PlayMelodyFlag = TRUE;
const struct
{
char tune1[128];
char tune2[65];
int defaultoctave;
int defaultduration;
int tempo;
}SilentNight = {
{"f#.,8g#,f#,d#.,p.,f#.,8g#,f#,d#.,p.,2c#6,c#6,a#.,p.,2b,b,f#.,p.,2g#,g#,b.,8a#,g#,f#.,8g#,f#,d#.,p.,2g#,g#,b.,8a#,g#,f#.,8g#,f#,"},{"d#.,p.,2c#6,c#6,e.6,8c#6,a#,2b.,2d#6,p.,b,f#,d#,f#.,8e,c#,b.4,1p"},
5,
DURATION_4,
140
};
const struct
{
char tune1[128];
char tune2[75];
int defaultoctave;
int defaultduration;
int tempo;
}JingleBells = {
{"8e.,8e.,e.,8e.,8e.,e.,8e.,8g.,c,16d.,2e,p,8f.,8f.,f,16f.,8f.,8e.,8e.,16e.,16e.,8e.,8d.,8d.,8e.,d.,g.,8e.,8e.,e.,8e.,8e.,e.,8e.,"},{"8g.,c,16d.,2e,p,8f.,8f.,f,16f.,8f.,8e.,8e.,16e.,16e.,8g.,8g.,8f.,8d.,c.,1p"},
5,
DURATION_4,
180
};
/* Function Prototypes */
void InitTimer(void);
int PlayMelody();
void PlayNote(long note, int octave, int duration);
char get_char_from_tune(long index);
int get_tempo(void);
int get_defaultoctave(void);
int get_defaultduration(void);
void Melody_Task(void);
//-----------------------------------------------------------------------------
// Start of Code
//-----------------------------------------------------------------------------
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void main(void)
{
TRISCbits.TRISC2 = 0;
InitTimer();
enable_interrupts(GLOBAL);
Melody_Pointer = JINGLEBELLS;
while(1)
{
Melody_Task();
}
}
/* *************************************************************************
DESCRIPTION: This function handles the playing of a melody
RETURN: True if the melody is still active or False if its complete
ALGORITHM: none
NOTES: none
*************************************************************************** */
int PlayMelody(void)
{
int octave = 0;
int duration = 0;
long note = 0;
// Check for a valid Melody
if (Melody_Pointer >= LAST_MELODY)
{
// Reset the Melody to the start
Melody_Pointer = 0;
Note_Index = 0xFFFF;
}
// Load notes while we have enough room
while (Notestat.Count < MAX_NOTE_BUFFER_SIZE)
{
// Is this the first note?
if (Note_Index == 0xFFFF)
{
Tempo = get_tempo();
Note_Index = 0;
}
// Set Default duration
duration = get_defaultduration();
// Set Default Octave
octave = get_defaultoctave();
// Play a bit of slience between notes
if (get_char_from_tune(Note_Index) == ',')
{
PlayNote(0, 4, DURATION_32);
Note_Index++;
return(TRUE);
}
// We are checking the duration
else if ((get_char_from_tune(Note_Index) == '3') && (get_char_from_tune(Note_Index+1) == '2'))
{
duration = DURATION_32;
Note_Index += 2;
}
else if ((get_char_from_tune(Note_Index) == '1') && (get_char_from_tune(Note_Index+1) == '6'))
{
duration = DURATION_16;
Note_Index += 2;
}
else if (get_char_from_tune(Note_Index) == '8')
{
duration = DURATION_8;
Note_Index++;
}
else if (get_char_from_tune(Note_Index) == '4')
{
duration = DURATION_4;
Note_Index++;
}
else if (get_char_from_tune(Note_Index) == '2')
{
duration = DURATION_2;
Note_Index++;
}
else if (get_char_from_tune(Note_Index) == '1')
{
duration = DURATION_1;
Note_Index++;
}
// Now we get the note
switch (get_char_from_tune(Note_Index++))
{
case 'c':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_C_SHARP;
Note_Index++;
}
else
note = NOTE_C;
break;
case 'd':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_D_SHARP;
Note_Index++;
}
else
note = NOTE_D;
break;
case 'e':
note = NOTE_E;
break;
case 'f':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_F_SHARP;
Note_Index++;
}
else
note = NOTE_F;
break;
case 'g':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_G_SHARP;
Note_Index++;
}
else
note = NOTE_G;
break;
case 'a':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_A_SHARP;
Note_Index++;
}
else
note = NOTE_A;
break;
case 'b':
note = NOTE_B;
break;
case 'p': // slience
note = NOTE_SILENCE;
break;
}
// See if this note is 1.5x the duration
if (get_char_from_tune(Note_Index) == '.')
{
// Use the MSB to signify 1.5x
duration |= 0x80;
Note_Index++;
}
// Get the octave
switch (get_char_from_tune(Note_Index))
{
case '4':
octave = 4;
Note_Index++;
break;
case '5':
octave = 5;
Note_Index++;
break;
case '6':
octave = 6;
Note_Index++;
break;
case '7':
octave = 7;
Note_Index++;
break;
default:
break;
}
// Sometimes the duration multiplier comes after the octave
if (get_char_from_tune(Note_Index) == '.')
{
/* Duration 1.5x */
duration |= 0x80;
Note_Index++;
}
// Play the note (we actually just load it in a buffer
PlayNote(note, octave, duration);
// Is this the end?
if (get_char_from_tune(Note_Index) == 0)
{
Note_Index = 0xFFFF;
return(FALSE);
}
}
return(TRUE);
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void PlayNote(long note, int octave, int duration)
{
long duration_count;
// Process octave
switch (octave)
{
case 4 :
break;
case 5 :
note = note >> 1;
break;
case 6 :
note = note >> 2;
break;
case 7 :
note = note >> 4;
break;
}
// Process Note Duration
duration_count = 256;
duration_count >>= (duration & 0x7F);
// If duration is 1.5x add .5 to duration
if (duration & 0x80)
duration_count += (duration_count >> 1);
// Add the note to our buffer
NoteBuffer[Notestat.Tail].note = note;
NoteBuffer[Notestat.Tail].duration = duration_count;
Notestat.Tail++;
Notestat.Tail &= NOTE_ROLLOVER_MASK;
Notestat.Count++;
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void InitTimer(void)
{
setup_timer_0(RTCC_DIV_256 | RTCC_8_BIT);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_CCP1);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_TIMER2);
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
char get_char_from_tune(long index)
{
switch (Melody_Pointer)
{
case SILENTNIGHT:
if (index<127)
return (SilentNight.tune1[index]);
else
return (SilentNight.tune2[index-127]);
break;
case JINGLEBELLS:
if (index<127)
return (JingleBells.tune1[index]);
else
return (JingleBells.tune2[index-127]);
break;
default:
break;
}
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
int get_tempo(void)
{
switch (Melody_Pointer)
{
case SILENTNIGHT:
return (SilentNight.tempo);
break;
case JINGLEBELLS:
return (JingleBells.tempo);
break;
default:
break;
}
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
int get_defaultoctave(void)
{
switch (Melody_Pointer)
{
case SILENTNIGHT:
return (SilentNight.defaultoctave);
break;
case JINGLEBELLS:
return (JingleBells.defaultoctave);
break;
default:
break;
}
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
int get_defaultduration(void)
{
switch (Melody_Pointer)
{
case SILENTNIGHT:
return (SilentNight.defaultduration);
break;
case JINGLEBELLS:
return (JingleBells.defaultduration);
break;
default:
break;
}
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void Melody_Task(void)
{
if (PlayMelodyFlag)
{
if (PlayMelody()==0)
Melody_Pointer++;
}
}
//----------------------------------------------------------------------------
// ISR routines
//----------------------------------------------------------------------------
#int_ccp1
/* *************************************************************************
DESCRIPTION: This function controls the PWM of the piezo speaker
RETURN: none
ALGORITHM: none
NOTES: If you do not wish to use C2 as the output, then you will need
to toggle your output here. Make sure that you change the CCP
setup not to toggle the C2 output if this is the case
*************************************************************************** */
void ccp1_isr (void)
{
CCP_1 += Note_Ticks;
#if defined(__PCM__)
output_toggle(PIN_C2);
#endif
}
/* *************************************************************************
DESCRIPTION: This function is used to control the duration of the note
RETURN: none
ALGORITHM: none
NOTES: I store the notes in a buffer so that the main loop has other
time to do stuff with out have to sit at wait for a note to
complete.
*************************************************************************** */
#int_timer0
void timer0_isr (void)
{
// Preload a value for TMR0 so that we can control how long it takes to
// trigger an interrupt
TMR0 = Tempo;
// Is a note playing?
if (DurationCount)
{
DurationCount--;
if (!DurationCount)
setup_ccp1(CCP_OFF);
}
// Note is finished playing, do we have anymore in our buffer?
else if (Notestat.Count)
{
DurationCount = NoteBuffer[Notestat.Head].duration;
Note_Ticks = NoteBuffer[Notestat.Head].note;
Notestat.Count--;
Notestat.Head++;
Notestat.Head &= NOTE_ROLLOVER_MASK;
CCP_1 = TMR1 + Note_Ticks;
if (Note_Ticks)
{
/* Setup the CCP module to toggle the output pin c2 */
#if defined(__PCH__)
setup_ccp1(CCP_COMPARE_TOGGLE_MATCH);
#else
setup_ccp1(CCP_COMPARE_INT);
#endif
}
// Nope, we are all through so disable the PWM
else
{
setup_ccp1(CCP_OFF);
}
}
}
-
Hola.
Pues la idea sería mas o menos asi: Se va leyendo las posiciones del código tipo 1A.N en donde:
1: Seria la octava
2: Nota
3: #, b, . (. para la nota sin modificaciones tonales)
4: Duracion temporal (R: Redonda, B: Blanca, N: Negra ...)
Con eso debes configurar el modulo de PWM para sacar la frecuencia determinada a la nota y con algun timer controlas la duracion temporal de la nota, entonces vas leyendo de 4 bytes en 4 bytes y vas identificando los valores correpondientes.
Saludos
-
Ok boy a investigar mas afondo el código rtttl. es una pena que el ejemplo que encontré este tan enredado. :( :(
saludos
-
Por fin e conseguido descifrar la trama del código rtttl :-/ :-/ :-/ con lo que e conseguido compilar un pequeño ejercicio el cual a pesar de que la melodía es entendible tiene ciertas deficiencias a motivo de ciertas cuestiones que no logro entender a continuación las menciono.
1- el código rtttl dentro se su trama me marca silencios (p) pero en la librería de tones.c no esta considerada esta cuestión, solo tiene las notas musicales por lo que no se como implementar estos silencios.
2- La cuestión de la duración de los tiempos en que se mantiene la nota no me queda clara ya que la trama del código rttl considera estos tiempos de la siguiente manera
1 redonda
2 blanca
4 negra
8 corchea
16 semicorcha
32 fusa
Pero no da como referencia valor alguno para estas notas (no se si ese sea su nombre correcto)
Así que investigando por la red alguien dedujo de manera empírica esto y asigno los siguientes valores
Redonda 2seg
Blanca 1seg
Negra 500ms
Corchea 250ms
Semicorchea 125ms
Fusa 62ms
Ahora aunque estos valores parecen funcionar la melodía no es 100% precisa
Según e estado leyendo esto talves se Deva a que el tiempo de estas” notas” no es siempre el mismo ya que depende del tiempo que dure la pieza para lo cual le encuentro sentido a un valor dentro de la trama del código rttl que me dice lo siguiente(tiempos*minuto=250).
Habrá que calcular la duración de estas “notas” en función de la duración de este parámetro (tiempos*minuto)????? O en su defecto para que sirve este parámetro (tiempos*minuto)
3- dentro de la librería de tones.c no esta implementada esta nota f# como se podría hacer para alcanzar esta nota a caso cambiando a f de actava ¿??
Dejo el programa para que alguien con mejor oído musical me haga favor de indicarme que esta fallando
Saludos
PD. El maldito pic canto primero que yo :D :D :D :D
-
Este es el código rtttl que tome para el ejercicio:
Muppets:d=4,o=5,b=250:c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,8a,8p,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,8e,8p,8e,g,2p,c6, c6,a,b,8a,b,g,p,c6,c6,a,8b,a,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,d,8d,c
Aquí el código utilizando la librería tones.c
//// ////
//// Configure the CCS prototype card as follows: ////
//// Connect the positive wire of the speaker to pin B0 ////
//// Connect the negative wire of the speaker to Gnd ////
//// ////
//// This example will work with the PCM and PCH compilers. The ////
//// following conditional compilation lines are used to include a ////
//// valid device for each compiler. Change the device and clock ////
//// pins for your hardware if needed. ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////
#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#endif
#include <tones.c>
#define SIZE 56
const struct note
{
long tone;
long length;
} MUPPETS[SIZE] = {
C_note[2],500, c_note[2],500, A_note[1],500, B_note[1],500, A_note[1],250, B_note[1],500,
G_note[1],500, C_note[2],500, C_note[2],500, A_note[1],500, B_note[1],250,
A_note[1],500, G_note[1],500, E_note[1],500, E_note[1],500,
E_note[1],500, G_note[1],500, F_note[1],500, E_note[1],250, F_note[1],500, C_note[2],250,
C_note[2],250, C_note[1],250, D_note[1],250, E_note[1],500, E_note[1],250, E_note[1],250, E_note[1],250, E_note[1],250,C_note[2],500, C_note[2],500,
A_note[1],500, B_note[1],500, A_note[1],250, B_note[1],500, G_note[1],500,
C_note[2],500, C_note[2],500, A_note[1],500, B_note[1],250, A_note[1],500, G_note[1],750, E_note[1],500, E_note[1],500, G_note[1],500, F_note[1],500, E_note[1],500,
F_note[1],500, C_note[2],250, C_note[1],250, D_note[1],250, E_note[1],500, E_note[1],250,
D_note[1],500, D_note[1],250, C_note[1],500};
void main(void) {
int i;
while(TRUE)
{
for(i=0; i<SIZE; ++i)
{
generate_tone(MUPPETS[i].tone,MUPPETS[i].length);
delay_ms(75);
}
}
}
-
Hola.
El F# es medio tono mas alto que el F.
Para los silencios, bastaria con apagar el modulo de PWM y no sacar ninguna frecuencia.
Con respecto a la duracion temporal de las figuras, lo realmente importante es la relacion que hay entre ellas:
1 Redonda = 2 Blancas
1 Blanca = 2 Negras
1 Negra = 2 Corcheas
1 Corchea = 2 Semicorcheas
..
Tu decidiras cual es el valor mas conveniente -se asume 2 segundos para la Redonda para que la pieza posea una buena cadencia-.
Saludos
-
Ok te agradezco aquí cabe aclarar que estoy utilizando la librería de tones.c la cual a mi entender no utiliza el modulo pmw ya que la salida es por pin_b0.
Como mencione esta Liberia no toma en cuenta la posibilidad de hacer silencios y la nota f#
Este librería pide que las notas se escriban una tras otra en un arreglo de array por lo que no le encuentro como agregar código para que el pin_b0 se que de mudo.en el propio ejemplo de ccs se tiran las notas de corrido sin silencios.
Por lo cual la única posibilidad que le encuentro es meterle mano ala librería para conseguir esto lo cual escapa de mis conocimientos.
En definitiva por lo que experimentado asta el momento la librería tones permite hacer cantar al pic muy fácilmente. Aunque deja mal sabor de boca lo deseable seria hacer un reproductor de código rttl mucho mas rico en el sentido de que permite utilizar silencios y toma en cuenta la latencia de la pieza(tiempos * minuto) además de que este método utiliza el pmw.
Aunque por ahora ese proyecto queda en la lista de pendientes a espera a que avance en mis conocimientos de programación y el compilador ccs.
Saludos
-
Funciona :-/ :-/ :-/ :-/ :-/ :-/ el pic esta cantando al estudiar la librería tones no fue difícil agregar las notas f# y c# así como p (silencio).
El único detalle es que aun no encuentro y no se si sea posible aumentar o disminuir el ritmo de la pieza (a que velocidad se reproduce) para conseguir esto por ahora hay que jugar con el tiempo que dura la nota, para hacer la pieza mas rápida se disminuye el tiempo por defecto de las notas.
Por fin adiós a la tonadita de siempre de las series navideñas.
Por cierto alguien conocerá algún convertidor de midi a rttl de ser posible que sea de libre uso ¿??¿?
Saludos
-
Hola septiembre_negro, crees que se pueda ver el código de ejemplo que hiciste y el hard?
saludos y espero no incomodar con la petición, si fuera así no hagas caso a mi mensaje.
-
Por supuesto no tiene mayor complicación todo esta basado en la librería tones.c esta librería entrega la frecuencia correspondiente a cada nota. El problema que tuve fue que sin tener conocimientos musicales estaba más que en chino leer una partitura para así poder darle las notas al pic para que cantara.
Esto se resuelve gracias al código rttl ya que este código en modo texto te entrega la información que se requiere, tiempo (que se sostiene la nota), nota, octava y no queda mas que codificar o interpretar esta información según la librería tones.c.
Esta interpretación o codificación yo las ago a papel ya que mis conocimientos son limitados para poder lograr el algoritmo que interprete este código de forma automática
Aquí lo importante es entender el código rttl que esta más que explicado en un enlace que pongo mas arriba en este mismo hilo.
http://personal.telefonica.terra.es/web/japus/rtplayer_es.html
Ahora en cuanto al hard no hay mayor complicación que conectar el buzer al portb.0 del pic (así viene en la librería por defecto pero como sabrás mejor que yo se puede cambiar puer cualquier otro pin.
Aquí el código de lo que llevo al momento.
-
Todo se entiende mejor con un ejemplo este es el código rttl de la melodía silent night es importante que te bases solo en esta melodía para entender como pasar de rttl a las notas de la librería notes por que las otras dos están modificadas cambie la octava y el tiempo y por lógica no le vas a encontrar relación.
silent night=noche de paz
Aquí el código rttl :
Silent Night: d=4,o=5,b=140:
f#., 8g#, f#, d#., p, 8p, f#., 8g#, f#, d#., p, 8p, 2c#6, c#6, a#., p, 8p, 2b, b, f#., p, 8p, 2g#, g#, b., 8a#, g#, f#., 8g#, f#, d#., p, 8p, 2g#, g#, b., 8a#, g#, f#., 8g#, f#, d#., p, 8p, 2c#6, c#6, e.6, 8c#6, a#, 2b., 2d#6, p, 8p, b
codigo ccs:
#include <tones.c>
#define SIZE 54
const struct note
{
long tone;
long length;
}noche_de_paz[SIZE] = {
Fb_note[1],750, Gb_note[1],250,Fb_note[1],500, Db_note[1],500, P_note[1],500,
P_note[1],250, Fb_note[1],750, Gb_note[1],250, Fb_note[1],500, Db_note[1],500,
P_note[1],500, P_note[1],250, Cb_note[2],500, Ab_note[1],750, P_note[1],500,
P_note[1],250, B_note[1],1000, B_note[1],500, Fb_note[1],750, P_note[1],500,
P_note[1],250, Gb_note[1],1000, Gb_note[1],500, B_note[1],750, Ab_note[1],250,
gb_note[1],500, Fb_note[1],750, Gb_note[1],250, Fb_note[1],500, Db_note[1],750,
P_note[1],500, P_note[1],250, Gb_note[1],1000, Gb_note[1],500, B_note[1],750,
A_note[1],250, Gb_note[1],500, Fb_note[1],750, Gb_note[1],250, FB_note[1],500,
D_note[1],750, P_note[1],500, P_note[1],250, Cb_note[2],1000, Cb_note[2],500,
E_note[2],750, Cb_note[2],250, Ab_note[1],500, B_note[1],998, Db_note[2],1000,
P_note[1],500, P_note[1],250, B_note[1],500};
#define SIZE2 25
const struct note2
{
long tone2;
long length2;
}jingle_bell[SIZE2] = {
B_note[1],500, B_note[1],500,B_note[1],500, P_note[1],125, B_note[1],500,
B_note[1],500, B_note[1],500, P_note[1],125, B_note[1],250,D_note[2],250
G_note[1],250, A_note[1],250, B_note[1],500, C_note[2],250, C_note[2],250,
C_note[2],500, B_note[1],250, B_note[1],250, B_note[1],500, B_note[1],250,
A_note[1],250, A_note[1],250, B_note[1],250, A_note[1],500, D_note[2],250};
#define SIZE3 42
const struct note3
{
long tone3;
long length3;
}litte_dankey[SIZE3] = {
E_note[1],250, E_note[1],250,G_note[1],1000, E_note[1],500, F_note[1],250,
F_note[1],250, A_note[1],1000,F_note[1],500, E_note[1],250, E_note[1],250,
G_note[1],1000, E_note[1],500,D_note[1],1000, P_note[1],1000, E_note[1],250,
E_note[1],250, G_note[1],1000,E_note[1],500, F_note[1],250, F_note[1],250,
A_note[1],1000, F_note[1],500,G_note[1],250, G_note[1],250, B_note[1],1000,
G_note[1],500, C_note[2],1000,P_note[1],1000, C_note[2],1000, C_note[2],500,
C_note[1],500, B_note[1],750,A_note[1],250, G_note[1],1000, A_note[1],500,
B_note[1],250, A_note[1],250,G_note[1],1000, A_note[1],500, B_note[1],250,
A_note[1],250, G_note[1],1000};
void main()
{ int i;
INT J;
INT K;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
// TODO: USER CODE!!
while(TRUE)
{
for(i=0; i<SIZE; ++i)
{
generate_tone(noche_de_paz[i].tone,noche_de_paz[i].length);
delay_ms(75);
}
delay_ms(2000);
for(j=0; j<SIZE2; ++j)
{
generate_tone(jingle_bell[j].tone2,jingle_bell[j].length2);
delay_ms(20);
}
delay_ms(2000);
for(K=0; K<SIZE3; ++K)
{
generate_tone(litte_dankey[K].tone3,litte_dankey[K].length3);
delay_ms(75);
}
delay_ms(2000);
}
}
-
Aquí la librería tones.c modificada
////////////////// Driver to generate musical tones /////////////////////
//// ////
//// generate_tone(frequency, duration) Generates wave at set ////
//// frequency (Hz) for set ////
//// duration (ms) ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2003 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////
#ifndef MUSIC_NOTES
#define MUSIC_NOTES
// NOTE FREQUENCY
// Octave0 Octave1 Octave2 Octave3
const long Cb_NOTE[4] ={ 277, 554, 1109, 2217};
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 Fb_NOTE[4] ={ 370, 740, 1480, 2960};
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};
const long P_NOTE [4] ={ 0, 0, 0, 0, };
#endif
#define TONE_PIN PIN_B0
void do_delay(int ms_delay, int num_ms, int us_delay, int num_us) {
int i;
for(i=0;i<num_ms;i++)
delay_ms(250);
delay_ms(ms_delay);
for(i=0;i<num_us;i++)
delay_us(250);
delay_us(us_delay);
}
void generate_tone(long frequency, long duration)
{
int32 total_delay_time; // in microseconds
long total_ms_delay_time, total_us_delay_time;
int num_us_delays, num_ms_delays, ms_delay_time, us_delay_time;
long num_periods;
total_delay_time = (1000000/frequency)/2-10; // calculate total delay time (10 for error)
total_ms_delay_time = total_delay_time/1000; // total delay time of ms
num_ms_delays = total_ms_delay_time/250; // number of 250ms delays needed
ms_delay_time = total_ms_delay_time%250; // left over ms delay time needed
total_us_delay_time = total_delay_time%1000; // total delay time of us (ms already acounted for)
num_us_delays = total_us_delay_time/250; // number of 250us delays needed
us_delay_time = total_us_delay_time%250; // left over us delay time needed
num_periods = ((int32)duration*1000)/(1000000/frequency);
while((num_periods--) != 0)
{
do_delay(ms_delay_time, num_ms_delays, us_delay_time, num_us_delays);
output_high(TONE_PIN);
do_delay(ms_delay_time, num_ms_delays, us_delay_time, num_us_delays);
output_low(TONE_PIN);
}
return;
}
-
Me hubiera encantado comentar todo en una sola respuesta pero con una conexión a 32kbps hay que darse mañas.
Bueno cuando lo analices te darás cuenta que es una pasada realmente lo único que ago es interpretar el código rttl y codificarlo a como entrega las notas la librería tones cualquier duda estamos pendientes.
Ahora cabe puntualizar dos cosas lo realmente interesante de este proyecto seria lograr un reproductor de código rttl.
Asea que el pic lea directamente la trama rttl (evitando así lo que ago a papel)
El código rttl lleva en su nacimiento el pecado nació para melodías de teléfono por lo cual son de corta duración . para que el pic interprete una canción completa hay que buscar en otro terreno las melodías midi, lo cual implica convertir de midi a rttl estos convertidores existen pero desafortunadamente los que e encontrado requieren licencia y en modo de prueba no entregan el código rttl
-
:shock: guau cuanta info, ya tengo para rato
muchas gracias septiembre_negro :-/
-
Pues que te diviertas 8) ;-) y si alguien encuentra como resolver lo de convertir midi a rtttl que pegue un grito :?
-
Pues bien después de un largo recorrido por la word web e encontrado como convertir archivos midi a rttl realizando una prueba preliminar con 100 notas en resultado es mas que aceptables :-/ :-/ en la inteligencia que estamos hablando de tonos monofónicos.
Ahora me dispongo a realizar pruebas con una melodía completa 285 notas :shock: :shock:
Aunque cabe aclaras que con un editor de midi podemos cortar la melodía a demás de otras cosas como eliminar pistas cambiar el instrumento de una pista el tiempo octava crear melodías propias. ;-)
En una próxima etapa esta considerada la amplificación del audio y el control de volumen digital con unos bichitos que texas tubo a bien mandarme, se podría pensar que para tonos monofónicos es una exageración y así es :mrgreen: la idea principal es introducirse mas afondo en estos chismes para mas adelante migrar el proyecto a archivos de audio mas complejos como midi y por que no mp3 el cielo es el limite :-/ :-/ :-/ :-/
Por lo que hay para entretenerse un buen tiempo y mejorar los resultados.
-
Pues nada sigo sin conseguir la conversión de midi a rttl, encontré este conversor en línea http://midi.mathewvp.com/ .
Las primeras pruebas fueron con pocas notas por lo que no me percate que este convertidor entrega valores para la duración de la nota de 1 asta 384.
Y el protocolo rtttl para la duración de la nota tiene valores de 1, 2, 4, 8, 16,32 así que este convertidor no es compatible, a los valores que entrega no le encuentro relación alguna con el tiempo de duración ya que si estuviera dado en segundos es imposible que una nota dure 384 segundos, si fueran milisegundos es imposible que una nota dure 1 milisegundo.
Así que continúo buscando desesperadamente un maldito convertidor de midi a rtttl :5] :5] :5]
-
mhh, creo que el formato MIDI es muy complejo respecto al formato rtttl, por lo que quedarían muchos "huecos" para pasar de RTTTL a MIDI, y sobraría mucha información para pasar de MIDI a RTTTL.
Saludos
-
hola septiembre_negro,
He leido todo el hilo pero me confundi un poco, en el sentido de saber si ya tienes la melodia que deseabas para que lo "cante" (decodifique) el pic. Mi intención es ayudar pues yo tambien trabaje con esa libreria del ccs (tonces.c) y realize unas canciones con ella.
Saludos.
-
mhh, creo que el formato MIDI es muy complejo respecto al formato rtttl, por lo que quedarían muchos "huecos" para pasar de RTTTL a MIDI, y sobraría mucha información para pasar de MIDI a RTTTL.
Saludos
Pues si efectivamente el formato midi es por mucho mas complejo que el rttl ,
Una melodía midi tiene mas de 10 pistas (ahora no recuerdo el número exacto) y cada pista se puede reproducir con un instrumento diferente.
De ahí el mayor problema para convertir a rttl ya que este código es monofónico.
Este problema se resuelve con un editor midi este editor permite escoger la pista que mejores resultados de al reproducirla en monofónico, recortar la misma etc.
Infortunadamente no me a sido posible encontrar un editor de estos solo tengo por seguro que existen.
El motivo por el cual me es necesario pasar de midi a rttl es como ya lo mencione mas arriba el formato rttl lleva en su nacimiento el pecado es un formato para ring tones por lo cual sus melodías son de poca duración y el repertorio que hay para escoger es muy limitado.
Por lo cual las únicas melodías que e encontrado en formato rttl son tonadas del tío SAM lo cual no me deja nada conforme ya que cualquier serie navideña china o tarjeta navideña aria exactamente lo mismo sin tanto lió y si mucho mas barato (dudo mucho que alguna de estas cosas que menciono tenga un microcontrolador en sus entrañas mas bien alguna araña china muy especifica)
Me hubiera encantado que el pic cantara algo mas hispánico :mrgreen: el niño del tambor, peses en el rió, ETS
-
hola septiembre_negro,
He leido todo el hilo pero me confundi un poco, en el sentido de saber si ya tienes la melodia que deseabas para que lo "cante" (decodifique) el pic. Mi intención es ayudar pues yo tambien trabaje con esa libreria del ccs (tonces.c) y realize unas canciones con ella.
Saludos.
Si me acido posible reproducir melodías con el pic pero los resultados no me dejan conforme por lo que expongo en mi respuesta a mlo.
Las melodías rttl se escuchan bien pero son de poca duración y no hay mucho de donde escoger.
Convertir de midi a rttl no me as dejado conforme ya que el convertidor en línea que probé no me permite editar el archivo midi por lo cual los resultados van de regulares a malos.
Te agradezco tu interés
Saludos
-
si te refieres al sonido metalico que genera el pic solito pues ni modo, a menos que le aplicas suavizadores o filtros antes de la salida del parlantito, pero esa rutina tones.c te permite obtener esos sonidos de las tarjetas navideñas. no es eso lo que quieres?
-
Hola
Con respecto a los sonidos metálicos no tengo problema soy consiente de las limitantes que tiene el pic en este aspecto. es mas que imposible pedirle el tono de un piano de cola.
Lo que no me deja contento es que no me fue posible gravar en el pic música a mi gusto por las siguientes cuestiones.
No tengo conocimientos es música por lo cual me es imposible leer directamente una partitura y codificarla según la librería tones.c
Debido a esto recurrí al formato rtttl ya que Este formato resuelve el problema al entregar en un formato texto tiempo,nota,octava,ets
Desgraciadamente las melodías rtttl que deambulan por la red dejan mucho que desear
Son muy cortas y el repertorio es muy escueto y repetitivo (intenta una búsqueda con rttl navideños y veras que te vas a encontrar con la mismas tonaditas una y otra ves, mama santa,rudolf,noche de paz y otras pocas que ahora no recuerdo.)
Saludos
-
ahhhhhhhhhhhhhh
ese era el resumen que esperaba leer :mrgreen:
entonces podemos empezar con el tutorial de lectura de partitura? pues si esperas codificarla segun la libreria tones.c (o cualquier otra escrita para un microcontrolador de 8 bits) directamente pues solo te queda hacer tu mismo un software que vincule ambos temas, lo cual no es del todo imposible, más bien lo veo muy interesante, es más ya se me antojo cual tortita selva negra mmmm ñomi ñomi, naturalmente que antes debes tener nociones de música pero no creas que es difícil, es sólo cuestion de saber sumar y contar.
tu diras cuando empezamos.
-
;-)
Bueno, ese tutorial en donde iria, porque la idea es que se aprenda a leer la partitura y de ahi migrar a algun soft no? Me apunto a esa micro_cadaver.
Saludos
-
hola MLO, creo que aca nomas pues esta amarrado y como bien dices luego vendria el software para hacer esas rutinas compatibles con el tones.c
que dice el amigo septiembre_negro? :o
-
Pues yo estoy más que puesto, aprender a entender una partitura como cultura general es más que interesante.
Resuelto esto seguiría hacer una prueba a mano (codificar a lápiz y papel de partitura a notes.c) y en este punto decidir si vale la pena diseñar un algoritmo para hacerlo de forma automático.
Este comentario viene por que hay que entender las limitaciones del pic para cantar. Es muy probare que los resultados no sean buenos la cuerda vocal de nuestro pic es monofónica y los matices que nos puede dar esta vos son muy muy limitados.
Anexo el siguiente ejerció para que tengan una idea de lo que hablo la melodía tamboriler originalmente tiene formato midi al pasarla a rttl (que seria algo parecido a lo que pretendemos lograr al pasar de partitura a tones.c) pierde demasiado si lo compilan y lo prueban podrán juzgar por si mismos
Saludos.
-
Bien aquí esta el ejerció en cuestión .en cuanto al código esta echo un desastre solamente estaba jugando para hacer unas prueba con una melodía completa esta pésimamente optimizado y hay mucho que esta demás o se podría hacer mejor aquí lo interesante es que reproduzcan la melodía y juzguen por ustedes mismos si merece la pena continuar con esto
#org 0x1eaf, 0x1FFF void loader16F877A(void) {} //protect bootloader code for the 8k 16F876/7
#include <tones.c>
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
int cont=1;
int pulsos;
int i=1;
#define SIZE 54
const struct note
{
long tone;
long length;
}noche_de_paz[SIZE] = {
Fb_note[1],750, Gb_note[1],250,Fb_note[1],500, Db_note[1],500, P_note[1],500,
P_note[1],250, Fb_note[1],750, Gb_note[1],250, Fb_note[1],500, Db_note[1],500,
P_note[1],500, P_note[1],250, Cb_note[2],500, Ab_note[1],750, P_note[1],500,
P_note[1],250, B_note[1],1000, B_note[1],500, Fb_note[1],750, P_note[1],500,
P_note[1],250, Gb_note[1],1000, Gb_note[1],500, B_note[1],750, Ab_note[1],250,
gb_note[1],500, Fb_note[1],750, Gb_note[1],250, Fb_note[1],500, Db_note[1],750,
P_note[1],500, P_note[1],250, Gb_note[1],1000, Gb_note[1],500, B_note[1],750,
A_note[1],250, Gb_note[1],500, Fb_note[1],750, Gb_note[1],250, FB_note[1],500,
D_note[1],750, P_note[1],500, P_note[1],250, Cb_note[2],1000, Cb_note[2],500,
E_note[2],750, Cb_note[2],250, Ab_note[1],500, B_note[1],998, Db_note[2],1000,
P_note[1],500, P_note[1],250, B_note[1],500};
#define SIZE2 25
const struct note2
{
long tone2;
long length2;
}jingle_bell[SIZE2] = {
B_note[1],500, B_note[1],500,B_note[1],500, P_note[1],125, B_note[1],500,
B_note[1],500, B_note[1],500, P_note[1],125, B_note[1],250,D_note[2],250
G_note[1],250, A_note[1],250, B_note[1],500, C_note[2],250, C_note[2],250,
C_note[2],500, B_note[1],250, B_note[1],250, B_note[1],500, B_note[1],250,
A_note[1],250, A_note[1],250, B_note[1],250, A_note[1],500, D_note[2],250};
#define SIZE3 42
const struct note3
{
long tone3;
long length3;
}litte_dankey[SIZE3] = {
E_note[1],250, E_note[1],250,G_note[1],1000, E_note[1],500, F_note[1],250,
F_note[1],250, A_note[1],1000,F_note[1],500, E_note[1],250, E_note[1],250,
G_note[1],1000, E_note[1],500,D_note[1],1000, P_note[1],1000, E_note[1],250,
E_note[1],250, G_note[1],1000,E_note[1],500, F_note[1],250, F_note[1],250,
A_note[1],1000, F_note[1],500,G_note[1],250, G_note[1],250, B_note[1],1000,
G_note[1],500, C_note[2],1000,P_note[1],1000, C_note[2],1000, C_note[2],500,
C_note[1],500, B_note[1],750,A_note[1],250, G_note[1],1000, A_note[1],500,
B_note[1],250, A_note[1],250,G_note[1],1000, A_note[1],500, B_note[1],250,
A_note[1],250, G_note[1],1000};
#define SIZE4 58
const struct note4
{
long tone4;
long length4;
}merri_chistmas[SIZE4] = {
c_note[1],500, f_note[1],500,f_note[1],250, g_note[1],250, f_note[1],250,
e_note[1],250, d_note[1],500,ab_note[0],500, d_note[1],500, g_note[1],500,
g_note[1],250, a_note[1],250,g_note[1],250, f_note[1],250, e_note[1],500,
c_note[1],500, e_note[1],500,a_note[1],500, a_note[1],250, ab_note[1],250,
a_note[1],250, g_note[1],250,f_note[1],500, d_note[1],500, c_note[1],250,
c_note[1],250, d_note[1],500,g_note[1],500, e_note[1],500, f_note[1],750,
p_note[1],250, c_note[1],500,f_note[1],500, f_note[1],500, f_note[1],500,
e_note[1],750, p_note[1],250,e_note[1],500, f_note[1],500, e_note[1],500,
d_note[1],500, c_note[1],750,p_note[1],250, c_note[1],500, a_note[1],500,
g_note[1],250, g_note[1],250,g_note[1],250, f_note[1],250, c_note[2],500,
c_note[1],500, c_note[1],250,c_note[1],250, d_note[1],500, g_note[1],500,
e_note[1],500, f_note[1],500,p_note[1],1000};
#define SIZE5 50
const struct note5
{
long tone5;
long length5;
}tamboriler[SIZE5] = {
p_note[1],2000, f_note[1],1000,p_note[1],125, g_note[1],500, p_note[1],62,
a_note[1],1000, p_note[1],125,a_note[1],500, p_note[1],62, a_note[1],500,
p_note[1],62, ab_note[1],250,p_note[1],62, a_note[1],250, p_note[1],62,
ab_note[1],500, p_note[1],62,a_note[1],2000, p_note[1],1000, f_note[1],500,
p_note[1],62, f_note[1],500,p_note[1],62, g_note[1],500, p_note[1],62,
a_note[1],500, p_note[1],62,a_note[1],500, p_note[1],62, a_note[1],500,
p_note[1],62, a_note[1],500,p_note[1],62, ab_note[1],250, p_note[1],62,
a_note[1],250, p_note[1],62,ab_note[1],500, p_note[1],62, a_note[1],2000,
p_note[1],1000, g_note[1],500,p_note[1],62, a_note[1],500, p_note[1],62,
ab_note[1],500, p_note[1],62,c_note[2],500, p_note[1],62, c_note[2],500};
#define SIZE6 50
const struct note6
{
long tone6;
long length6;
}tamboriler2[SIZE6] = {
p_note[1],62, c_note[2],500,p_note[2],62, d_note[2],500, p_note[2],62,
c_note[2],250, p_note[2],62,ab_note[1],250, p_note[1],250, a_note[1],500,
p_note[1],62, g_note[1],2000,p_note[1],200, g_note[1],500, p_note[2],62,
a_note[1],500, p_note[2],62,ab_note[1],500, p_note[2],62, c_note[2],500,
p_note[1],62, c_note[2],500,p_note[2],62, c_note[2],500, p_note[2],62,
d_note[2],500, p_note[2],62,db_note[2],250, p_note[2],62, d_note[2],250,
p_note[1],62, c_note[2],500,p_note[2],62, ab_note[1],1000, p_note[2],125,
d_note[2],250, p_note[2],62,c_note[2],250, p_note[2],62, ab_note[1],500,
p_note[1],62, a_note[1],1000,p_note[1],125, c_note[2],250, p_note[2],62,
ab_note[1],250, p_note[1],500,a_note[1],500, p_note[1],65, g_note[1],2000};
#define SIZE7 50
const struct note7
{
long tone7;
long length7;
}tamboriler3[SIZE7] = {
p_note[1],500, f_note[1],1000,p_note[2],125, g_note[1],500, p_note[2],62,
a_note[1],500, p_note[1],65,a_note[1],500, p_note[1],65, a_note[1],500,
p_note[1],65, a_note[1],500,p_note[2],62, ab_note[1],250, p_note[2],500,
a_note[1],250, p_note[1],500,ab_note[1],500, p_note[1],65, a_note[1],2000,
p_note[1],1000, g_note[1],250,f_note[1],250, p_note[1],500, g_note[1],500,
p_note[1],62, f_note[1],2000,p_note[2],2000, f_note[1],1000, p_note[2],125,
g_note[1],500, p_note[1],62,a_note[1],1000, p_note[1],125, a_note[1],500,
p_note[1],65, a_note[1],500,p_note[2],65, ab_note[1],250, p_note[2],500,
a_note[1],250, p_note[1],500,ab_note[1],500, p_note[1],65, a_note[1],2000,
p_note[1],1000, f_note[1],500,p_note[2],62, f_note[1],500, p_note[2],62};
#define SIZE8 50
const struct note8
{
long tone8;
long length8;
}tamboriler4[SIZE8] = {
g_note[1],500, p_note[1],65,a_note[1],500, p_note[1],65, a_note[1],500,
p_note[1],65, a_note[1],500,p_note[1],62, a_note[1],500, p_note[1],62,
a_note[1],500, p_note[1],65,ab_note[1],250, p_note[1],65, a_note[1],250,
p_note[1],500, ab_note[1],500,p_note[1],65, a_note[1],2000, p_note[1],1000,
g_note[1],500, p_note[1],65,a_note[1],500, p_note[1],65, ab_note[1],500,
p_note[1],65, c_note[2],500,p_note[1],65, c_note[2],500, p_note[1],65,
c_note[2],500, p_note[1],65,c_note[2],500, p_note[2],65, d_note[2],500,
p_note[2],65, c_note[2],250,p_note[1],500, ab_note[1],250, p_note[1],500,
a_note[1],500, p_note[1],65,g_note[1],2000, p_note[1],1000, g_note[1],500,
p_note[1],65, a_note[1],500,p_note[1],65, ab_note[1],500, p_note[1],65,};
#define SIZE9 50
const struct note9
{
long tone9;
long length9;
}tamboriler5[SIZE9] = {
c_note[2],500, p_note[1],65,c_note[2],500, p_note[1],65, c_note[2],500,
d_note[2],500, p_note[1],65,db_note[2],250, p_note[1],500, d_note[2],500,
p_note[2],500, c_note[2],500,p_note[2],65, ab_note[1],1000, p_note[2],125,
d_note[2],500, p_note[1],500,c_note[2],250, p_note[1],500, ab_note[1],500,
p_note[2],65, a_note[1],1000,p_note[2],125, c_note[2],500, c_note[2],250,
p_note[2],500, ab_note[1],250,p_note[2],500, a_note[1],500, p_note[2],62,
g_note[1],2000, p_note[1],500,f_note[1],1000, p_note[1],125, g_note[1],500,
p_note[1],62, a_note[1],500,p_note[2],62, a_note[1],500, p_note[2],62,
a_note[1],500, p_note[1],65,a_note[1],500, ab_note[1],250, p_note[2],500,
a_note[1],250, p_note[1],500,ab_note[1],500, p_note[1],65, a_note[1],2000,};
#define SIZE10 8
const struct note10
{
long tone10;
long length10;
}tamboriler6[SIZE10] = {
a_note[1],2000, p_note[1],500,g_note[1],250, f_note[1],250, p_note[2],500,
g_note[1],500, p_note[1],65,f_note[1],2000};
void main()
{ int i;
INT J;
INT K;
INT L;
int m;
int n;
int O;
int p;
int q;
int r;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
//setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
//SET_TIMER0(130);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_tris_B(0b00010000);
output_b(0b00000000);
set_tris_c(0b00000000);
output_c(0b00000000);
enable_interrupts(int_ext); //activar interrupcion externa
ext_int_edge(H_TO_L); //config. de int. por flando de bajada
enable_interrupts(GLOBAL); //todas las interrupciones desactivadas
// TODO: USER CODE!!
while(TRUE)
{
for(i=0; i<SIZE; ++i)
{
generate_tone(noche_de_paz[i].tone,noche_de_paz[i].length);
delay_ms(75);
}
delay_ms(2000);
for(j=0; j<SIZE2; ++j)
{
generate_tone(jingle_bell[j].tone2,jingle_bell[j].length2);
delay_ms(20);
}
delay_ms(2000);
for(K=0; K<SIZE3; ++K)
{
generate_tone(litte_dankey[K].tone3,litte_dankey[K].length3);
delay_ms(75);
}
delay_ms(2000);
for(L=0; L<SIZE4; ++L)
{
generate_tone(merri_chistmas[L].tone4,merri_chistmas[L].length4);
delay_ms(20);
}
delay_ms(2000);
for(m=0; m<SIZE5; ++m)
{
generate_tone(tamboriler[m].tone5,tamboriler[m].length5);
delay_ms(30);
}
for(n=0; n<SIZE6; ++n)
{
generate_tone(tamboriler2[n].tone6,tamboriler2[n].length6);
delay_ms(30);
}
for(o=0; o<SIZE7; ++o)
{
generate_tone(tamboriler3[o].tone7,tamboriler3[o].length7);
delay_ms(30);
}
for(p=0; p<SIZE8; ++p)
{
generate_tone(tamboriler4[p].tone8,tamboriler4[p].length8);
delay_ms(30);
}
for(q=0; q<SIZE9; ++q)
{
generate_tone(tamboriler5[q].tone9,tamboriler5[q].length9);
delay_ms(30);
}
for(r=0; r<SIZE10; ++r)
{
generate_tone(tamboriler6[r].tone10,tamboriler6[r].length10);
delay_ms(30);
}
delay_ms(2000);
}
}
-
hola septiembre_negro (que nick mas largo ejejej :D),
cuando mencionas que el pic es monofonico pues tienes razon, reproduce una salida a la vez, y si intentas reproducir un midi (con varios canales) pues pierdes de antemano.
si eres consciente de esto e insistes en obtener sonidos más complejos entonces tendra que revisar un hilo (http://www.todopic.com.ar/foros/index.php?topic=23610.0)
donde un pic puede reproducir un archivo *.WAV (usando pwm y una memoria SD) lo cual se aleja abismalmente de la idea que propuse.
otra solucion seria usar varios pics y hacer un concherto con ellos jejeje.
-
O se podría usar varios pines de salida para crear las armonías no? Lo verdaderamente dificil es generar el timbre del instrumento.
Con tres pines podríamos hacer acordes, asi que seria con 5 pines seria perfecto, tres para armonía y 2 para melodía (1 extra por si se quiere armonizar).
Saludos
-
Teoría Musical
Conceptos Básicos
Solfeo: Este es el nombre que reciben los ejercicios vocales encaminados a que toda persona desarrolle progresivamente la facultad de distinguir y entonar los intervalos, marcar la duración de las notas y familiarizarse asi con la lectura musical.
Ritmo: Es la conexión de las duraciones temporales de las notas, es decir, a la relación de los valores fuertes con los débiles.
Sonidos: Es todo ruido en el cual se permite apreciar tres cualidades a saber:
- Intensidad: Cualidad que permite distinguir un sonido fuerte de otro débil.
- Altura: Cualidad que permite un sonido grave de otro agudo.
- Timbre: Cualidad que permite distinguir los sonidos dados por los instrumentos diferentes, aunque dichos sonidos posean la misma intensidad y la misma altura.
El sonido es el resultado físico de una vibración en un lapso de tiempo. Estas vibraciones solo se pueden percibir dentro de ciertos limites. Los sonidos mas graves son resultado de pocas vibraciones por segundo (32 es el mínimo audible), mientras que los sonidos mas elevados son el resultado de muchas vibraciones por segundo.
Existen numerosos cuerpos sonoros que producen sonidos musicales, como cuerdas punteadas (arpa, guitarra, etc), cuerdas rozadas (familia de los violines), cuerdas percutidas (clavicordio, clave, piano, etc), las columnas de aire (flauta, oboe, clarín, etc) y las variadas percusiones (tambor, gong, platillos, etc) .... y bueno, por que no ... un piezo conectado a un pin del PIC.
Los signos de la música:
Pentagrama: Sinónimo de pauta o pautado, comprende 5 lineas horizontales paralelas y equidistantes, mas cuatro espacios, cada uno de los cuales esta situado entre dos lineas contiguas. Lineas y espacios se cuentan en dirección ascendente.
(http://oscrove.files.wordpress.com/2008/02/pentagrama1.jpg)
Notas: Las notas son signos en forma de puntos o de pequeños círculos que representan graficamente los diferentes sonidos musicales. La posición de las notas -ya en las lineas, ya en los espacios intermedios- muestra la altura del correspondiente sonido, en tanto que su forma determina la duracion con exactitud.
Las notas son siete y recibe los siguientes nombres: do, re, mi, fa, sol, la, si. La denominacion de las seis primeras notas se atribuye -quizá erróneamente- al monje benedictino Guido de Arezzo (Siglo XI). Se cantaba en ese entonces el Himno a San Juan Bautista y la primera silaba de los seis primeros versos correspondía melódicamente a los sonidos que Arezzo decidió nombrar así:
UT queant laxis
REsonare fibris
MIra gestorum
FAmuli tuorum
SOLve polluti
LAbii real tum
Sancte Iohannes.
Mas tarde se designo la nota SI asociando las dos iniciales de Sancte Iohannes. Por ser dificil de pronunciar la nota UT, hacia 1636 el cantante italiano Doni le dio el nombre de DO, que era la mitad de su apellido.
Antes de Arezzo, las notas se designaban por las primeras letras del alfabeto, es decir:
A(La) B(Si) C(Do) D(Re) E(Mi) F(Fa) G(Sol)
Esta notacion subsiste aun hoy en casi todo el mundo.
Como bien lo escribe el maestro RedPic....continuará
-
Interesante acotacion musical MLO, bueno entonces contigo seguimos esto? parece que septiembre_negro anda tras otras alternativas, o al menos eso me parecio.
offtopic:
mi apellido son 3 notas musicales: LA - RE- DO
ssaludos :-/
-
Interesante acotacion musical MLO, bueno entonces contigo seguimos esto? parece que septiembre_negro anda tras otras alternativas, o al menos eso me parecio.
offtopic:
mi apellido son 3 notas musicales: LA - RE- DO
ssaludos :-/
Me encuentro sumamente preocupado por que creo que tengo problemas para comunicarme :( y eso me asusta :( lo que yo dije fue.
1.- Pues yo estoy más que puesto, aprender a entender una partitura como cultura general es más que interesante.
2.- Resuelto esto seguiría hacer una prueba a mano (codificar a lápiz y papel de partitura a notes.c) y en este punto decidir si vale la pena diseñar un algoritmo para hacerlo de forma automático.
3.- Este comentario viene por que hay que entender las limitaciones del pic para cantar. Es muy probare que los resultados no sean buenos la cuerda vocal de nuestro pic es monofónica y los matices que nos puede dar esta vos son muy muy limitados.
Cita. Como bien lo escribe el maestro RedPic....continuará fin de la cita
Como bien lo escribiría yo estamos a la orden y atentos maestro mlo 8)
-
añap, entonces manos a la obra, en la noche posteare una idea que tengo del software para exportar los archivos canciones.c
saludos :-/
-
Lineas Adicionales: La extension de los sonidos producidos por los diversos instrumentos no es posible encerrarla en el estrecho ambito del pentagrama, por tal razon se usan lineas adicionales y las famosas claves. Las lineas adicionales son fragmentos de pautado que se ponen encima o debajo del pentagrama segun los sonidos sean agudos (por encima o superiores) o graves (por debajo o inferiores).
(http://oscrove.files.wordpress.com/2008/02/pentagrama2.jpg)
Clave: Es un signo mediante el cual se establece la colocacion que deberan tener las notas en el pentagrama. Dicho signo se repite invariablemente al principio de cada pentagrama y sobre una determinada linea. La clave da su nombre a todas las notas puestas sobre esa misma linea, lo cual permite fijar el emplazamiento de todas las demas notas.
Hay tres clases de claves, a saber:
* Para sonidos graves esta la clave de fa:
(http://mediateca.educa.madrid.org/imagen/imagenes/publicas/tam4/cf/cfibwqfsfyvow1zx.gif)
* Para sonidos intermedios la clave de do en tercera y cuarta linea, asi mismo para sonidos agudos se situa en la primera y segunda linea:
(http://blogs.librodearena.com/myfiles/gddd/do.png)
* Para sonidos agudos esta la clave de sol en primera y segunda lineas:
(http://mediateca.educa.madrid.org/imagen/imagenes/publicas/tam4/mg/mgffmpeqplj22b9a.gif)
La relacion tonal entre las claves es la siguiente:
(http://img21.imageshack.us/img21/4194/endecagrama.png)
Hare mas enfasis en la clave de sol, que es la que mas se encuentra por ahi en las partiruras ....
La clave de sol se coloca en la segunda linea del pentagrama y reciben asi el nombre de sol todas las notas situadas en esa segunda linea. Por esta razon el fa, se colocara inmediatamente debajo del sol en el primer espacio; el la encima del sol, en el segundo y asi sucesivamente.
Figuras y valores de las notas: Se llama figura a cada una de las diferentes formas que reciben las notas musicales para fijar su duracion. Por lo tanto cada figura representa una duracion o un valor determinado.
Existen siete figuras de notas, a saber:
- Redonda
- Blanca
- Negra
- Corchea
- Semicorchea
- Fusa
- Semifusa
Y la relacion temporal entre ellas se explica mejor en el siguiente grafico:
(http://img.socialpublicidad.com/g/m/154_6795cd42094.jpg)
El que toque en semifusas ... mejor dicho, veanlo ustedes mismos .. el temita de las abejitas jeje
to be continue
-
que buena teoria. acabo de llegar con unas copas encima de una reunion puff tendre que pasar para mañana la publicacion de mi aporte. no desespereis. :-/
-
:)
que envidia hombre .....
-
bueno MLO, si estuvieras por Lima te invitaria a tomar con unas :g) :g) :g), aunque esa vida me esta pasando factura, mi garganta esta muy gastada y estoy pensando seriamente en dejar las helenas.
en la noche subo mi aporte, seran unas imagenes de como sera el software, para ello estoy consultando a un amigo programador de software, de tal manera que no caeremos en incoherencias.
saludos!!!
-
;-)
Pues voy a estar por Ica desde el 19 al 27 de Noviembre .... podria hacerse algo no? jejejeje
-
bueno MLO, si estuvieras por Lima te invitaria a tomar con unas :g) :g) :g), aunque esa vida me esta pasando factura, mi garganta esta muy gastada y estoy pensando seriamente en dejar las helenas.
saludos!!!
Hermano tu di rana y yo brinco :-/ yo si te tomo la palabra en una de esas me auto envió aunque sea por fax a tierras andinas donde se presume de mujeres muy guapas
-
;-)
Pues voy a estar por Ica desde el 19 al 27 de Noviembre .... podria hacerse algo no? jejejeje
Mm pues vemos haber que podemos hacer en estos días de cualquier manera quedamos pendientes para la próxima temporada si es que llego :mrgreen:
-
Ica esta un poco lejitos de Lima, ademas el 27 me caso por civil, si llegas di el santo y seña: micro_cadaver.
Conversando con mi amigo, el programador, le plantee y me demostro que se puede hacer una interface grafica con un teclado de la cantidad de octavas que el tones.c soporte en la parte inferior de la ventana principal, luego en la parte central se puede esbozar una partitura con su clave SOL, y con el mouse pinchar en cada tecla para que en la partitura aparezcan los simbolos musicales correspondientes.
El detalle grafico lo posteare en la noche. saludos!!!
-
Haaaaaa ahora entiendo el porque de la noche de copas pues no queda mas que desear felicidad y buena ventura a los novios.
En cuanto al sof la idea que presentas suena muy bien por medio de un teclado grafico vas introduciendo las notas según la partitura que se esta leyendo y el sof genera la matriz de datos para copiar y pegar en el pic.
Aunque como siempre es mas fácil decirlo que hacerlo pero ya iremos viendo
-
Claro que suena facil, y no lo es, al menos para alguien como yo que de programacion de software no tengo mucha experiencia, pero mi amigo programador es un lobo de lobos. Y el desde su escritorio nos apoyara al respecto. :-/ :-/
-
bueno, aca les dejo el bosquejo de como hacer la interface grafica del software.
(http://img141.imageshack.us/img141/9829/bosquejointerfacegrafic.jpg)
en word:
http://www.4shared.com/file/147401617/22ac7904/BOSQUEJO_INTERFACE_GRAFICA.html
que opinan. :-/ :-/
-
Muy buena la interfas grafica :-/ :-/ aunque creo que para complicarse menos se podría omitir la parte de la partitura. ya que ciento que es redundante si partimos del supuesto que ya tenemos la partitura
Saludos
-
pero si no colocamos la partitura entonces como escribimos la cancion para generar los ritmos y las notas?
Me explico:
El tones.c requiere los siguientes parametros
- tempo: es una propiedad que es una referencia de velocidad que dura un compas (usaremos el 4/4 por ahora), como el pic no puede manejar calculos matematicos complicados, dejaremos configurados algunos valores discretos para seleccionar.
- tono de la nota: si es LA, La sostenido, o RE, etc...
- duracion de la nota: se apoyara en el "tempo", en tonces cada REDONDA dura el tempo (si no es asi corrijanme porfavor), una BLANCA la mitad de la REDONDA, y asi sucesivamente.
Se puede colocar el nombre de las notas tambien, y un sin numero de indicadores para hacer más flexible la escritura de los temas.
-
Mm creo que aquí tenemos enfocado el problema de manera diferente como yo lo miro es así.
1. tengo la partitura en mano (la descargue e imprimí)
2. por medio del piano grafico boy introduciendo las notas que boy leyendo de la partitura.
3. el sofwer va generando la matriz de datos producto de ir realizando la conversión de las notas del piano a los valores de la librería notes.c
4. al indicarle al sof que e terminado genera un archivo .txt para copiar y pegar al sof del pic.
Entonces así como yo lo miro esta de mas que el sof me genere gráficamente la partitura que ya tengo.
Aunque tan solo es mi opinión y no tiene que ser como digo ya que no tengo la menor idea si generar la partitura grafica represente mucho problema o tan solo termine siendo un plus.
-
ah.... que habias entendido por esa partitura, en realidad lo habia puesto como a manera de pantalla de salida nomas. La verdad ayuda mucho, la secuencia seria asi:
1. tengo la partitura en la mano (la plancha)
2. por medio del piano grafico voy introduciendo las notas, estas se van reflejando en la pantalla superior, donde se puede visualizar sobre una partitura las notas que vamos escribiendo, asi como su duracion (blanca negra corchea etc).
3. una vez q terminamos, le damos a generar archivo *.c
la partitura quedara como un registro de lo que escribistes, porsiacaso necesitas modificarlo algo o transportar tu "arreglo" a otro lugar donde se encuentre otra aplicacion.
que tal asi? vamos dandole forma. saludos :-/ :-/
PD: MLO no se pronuncia, donde estara...
-
Aca toy.
Ojo, debe ser la partitura y no una tablatura ;-)
El soft deberia identificar el tipo de nota (blanca, negra, etc) y la altura tonal de la misma según la armadura de clave -eso yo lo posteare mas tarde- y de ahi el soft generar el .c que seria un vector con las variables, en si seria un string no?
Saludos
-
entonces antes de continuar con el soft, algun aporte más, algo que le falte o asi queda?
-
Pues no, creo qué así como planteas la interfas esta muy bien ahora para quedar claro lo único que el pic es capas de interpretar es; nota, octava, duración de la nota
Adicionalmente se podría agregar el tiempo que dura la pieza me refiero a que la pieza se ejecute mas rápido o mas lento. pero esto hay que trabajarlo por que no lo e conseguido.
Para que quede mas claro lo que el sof debe generar es algo así
#define SIZE 54
const struct note
{
long tone;
long length;
}noche_de_paz[SIZE] = {
Fb_note[1],750, Gb_note[1],250,Fb_note[1],500, Db_note[1],500, P_note[1],500,
P_note[1],250, Fb_note[1],750, Gb_note[1],250, Fb_note[1],500, Db_note[1],500,
P_note[1],500, P_note[1],250, Cb_note[2],500, Ab_note[1],750, P_note[1],500,
P_note[1],250, B_note[1],1000, B_note[1],500, Fb_note[1],750, P_note[1],500,
P_note[1],250, Gb_note[1],1000, Gb_note[1],500, B_note[1],750, Ab_note[1],250,
gb_note[1],500, Fb_note[1],750, Gb_note[1],250, Fb_note[1],500, Db_note[1],750,
P_note[1],500, P_note[1],250, Gb_note[1],1000, Gb_note[1],500, B_note[1],750,
A_note[1],250, Gb_note[1],500, Fb_note[1],750, Gb_note[1],250, FB_note[1],500,
D_note[1],750, P_note[1],500, P_note[1],250, Cb_note[2],1000, Cb_note[2],500,
E_note[2],750, Cb_note[2],250, Ab_note[1],500, B_note[1],998, Db_note[2],1000,
P_note[1],500, P_note[1],250, B_note[1],500};
-
Pues si gusto eso es lo que pretendo el código rtttl lo recién lo descubrir pero sigo sin aclararme es posible utilizar este código como referencia para implementarlo con la librería notes del ccs. Me explico
Esto es un código rttl Simpsons:d=4,o=5,b=160:32p,c.6,e6,f#6,8a6,g.6,e6,c6,8a,8f#,8f#,8f#,2g
Como quedaría si es posible utilizando la librería notes de ccs??
Ahora lo obvio seria utilizar directamente el código rtttl en el pic pero para mi desgracia el ejemplo que encontré utiliza una lógica muy avanzada y lo único que e conseguido es un tremendo dolor de cabeza ya ni siquiera pretendo entenderlo por ahora .
Si esta en la capacidad de alguien entender este ejemplo que habría que hacer para introducir mas melodías, modificar las que ya tiene no implica problema se sustituye el código actual por el de la melodía a y ya estampero lo que pretendo es meter tantas melodías como lo permita la memoria del pic.
Aquí una breve descripción del código rttl
http://personal.telefonica.terra.es/web/japus/rtplayer_es.html
Y aquí el programa que encontré en los foros del ccs para incrementar el código rtttl desafortunadamente para mi como principiante esta mas que en chino
/* */
/* RTTTL Ring Tone Player for Microchip Microcontrollers */
/* */
/* This program was designed to run on the PICDEM2 Plus demo board from */
/* Microchip. */
/* */
/* Usage: */
/* S3 - Selects Melody */
/* S2 - Starts/Stops Melody */
/* */
/* This code was designed for a clock speed of 20MHz */
/* The target device was a PIC18F452. */
/* You can use the PIC16F877 by changing the setup of CCP1 to */
/* CCP_COMPARE_INT. You will also need to toggle the output pin in the */
/* CCP1 interrupt routine. */
/* */
/* Many of the tunes were downloaded from "www.mrtones.com" */
/*****************************************************************************/
#case
#list
#if defined(__PCH__)
#include "18F452.h"
#else
#include "16F876.h"
#endif
#device *=16
#define CLOCKSPEED 10000000
#define CCP_COMPARE_TOGGLE_MATCH 2
#use delay(CLOCK=CLOCKSPEED)
#fuses HS, NOWDT, NOLVP, PUT
#define TMR1_PRESCALE 8
#define NOTE_C_SHARP (((CLOCKSPEED/4)/277.18)/TMR1_PRESCALE) // 277.18Hz
#define NOTE_D_SHARP (((CLOCKSPEED/4)/311.13)/TMR1_PRESCALE) // 311.13 Hz
#define NOTE_F_SHARP (((CLOCKSPEED/4)/369.99)/TMR1_PRESCALE) // 369.99 Hz
#define NOTE_G_SHARP (((CLOCKSPEED/4)/415.30)/TMR1_PRESCALE) // 415.30 Hz
#define NOTE_A_SHARP (((CLOCKSPEED/4)/466.16)/TMR1_PRESCALE) // 466.16 Hz
#define NOTE_C (((CLOCKSPEED/4)/261.63)/TMR1_PRESCALE) // 261.63 Hz
#define NOTE_D (((CLOCKSPEED/4)/293.66)/TMR1_PRESCALE) // 293.66 Hz
#define NOTE_E (((CLOCKSPEED/4)/329.63)/TMR1_PRESCALE) // 329.63 Hz
#define NOTE_F (((CLOCKSPEED/4)/349.23)/TMR1_PRESCALE) // 349.23 Hz
#define NOTE_G (((CLOCKSPEED/4)/392.00)/TMR1_PRESCALE) // 392.00 Hz
#define NOTE_A (((CLOCKSPEED/4)/440.00)/TMR1_PRESCALE) // 440.00 Hz
#define NOTE_B (((CLOCKSPEED/4)/493.88)/TMR1_PRESCALE) // 493.88 Hz
#define NOTE_SILENCE 0
#define DURATION_32 5 // Duration = 2^x
#define DURATION_16 4 // Duration = 2^x
#define DURATION_8 3 // Duration = 2^x
#define DURATION_4 2 // Duration = 2^x
#define DURATION_2 1 // Duration = 2^x
#define DURATION_1 0 // Duration = 2^x
typedef enum
{
SILENTNIGHT,
JINGLEBELLS,
LAST_MELODY
}MELODIES;
typedef struct
{
int Head;
int Tail;
int Count;
} NOTESTAT;
typedef struct
{
long note;
long duration;
}NOTE_DEF;
struct
{
int TRISC0:1;
int TRISC1:1;
int TRISC2:1;
int TRISC3:1;
int TRISC4:1;
int TRISC5:1;
int TRISC6:1;
int TRISC7:1;
}TRISCbits;
#if defined(__PCH__)
#locate TRISCbits = 0xF94
#else
#locate TRISCbits = 0x87
#endif
long TMR1;
#if defined(__PCH__)
#locate TMR1 = 0xFCE
#else
#locate TMR1 = 0x0E
#endif
int TMR1L;
#if defined(__PCH__)
#locate TMR1L = 0xFCE
#else
#locate TMR1L = 0x0E
#endif
int TMR1H;
#if defined(__PCH__)
#locate TMR1H = 0xFCF
#else
#locate TMR1H = 0x0F
#endif
int TMR0;
#if defined(__PCH__)
#locate TMR0 = 0xFD6
#else
#locate TMR0 = 0x01
#endif
#define MAX_NOTE_BUFFER_SIZE 4
#define NOTE_ROLLOVER_MASK 0b00000011
NOTE_DEF NoteBuffer[MAX_NOTE_BUFFER_SIZE];
NOTESTAT Notestat = {0,0,0};
long DurationCount=0;
int Tempo=0;
long Note_Ticks=0;
MELODIES Melody_Pointer;
long Note_Index = 0xFFFF;
BOOLEAN PlayMelodyFlag = TRUE;
const struct
{
char tune1[128];
char tune2[65];
int defaultoctave;
int defaultduration;
int tempo;
}SilentNight = {
{"f#.,8g#,f#,d#.,p.,f#.,8g#,f#,d#.,p.,2c#6,c#6,a#.,p.,2b,b,f#.,p.,2g#,g#,b.,8a#,g#,f#.,8g#,f#,d#.,p.,2g#,g#,b.,8a#,g#,f#.,8g#,f#,"},{"d#.,p.,2c#6,c#6,e.6,8c#6,a#,2b.,2d#6,p.,b,f#,d#,f#.,8e,c#,b.4,1p"},
5,
DURATION_4,
140
};
const struct
{
char tune1[128];
char tune2[75];
int defaultoctave;
int defaultduration;
int tempo;
}JingleBells = {
{"8e.,8e.,e.,8e.,8e.,e.,8e.,8g.,c,16d.,2e,p,8f.,8f.,f,16f.,8f.,8e.,8e.,16e.,16e.,8e.,8d.,8d.,8e.,d.,g.,8e.,8e.,e.,8e.,8e.,e.,8e.,"},{"8g.,c,16d.,2e,p,8f.,8f.,f,16f.,8f.,8e.,8e.,16e.,16e.,8g.,8g.,8f.,8d.,c.,1p"},
5,
DURATION_4,
180
};
/* Function Prototypes */
void InitTimer(void);
int PlayMelody();
void PlayNote(long note, int octave, int duration);
char get_char_from_tune(long index);
int get_tempo(void);
int get_defaultoctave(void);
int get_defaultduration(void);
void Melody_Task(void);
//-----------------------------------------------------------------------------
// Start of Code
//-----------------------------------------------------------------------------
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void main(void)
{
TRISCbits.TRISC2 = 0;
InitTimer();
enable_interrupts(GLOBAL);
Melody_Pointer = JINGLEBELLS;
while(1)
{
Melody_Task();
}
}
/* *************************************************************************
DESCRIPTION: This function handles the playing of a melody
RETURN: True if the melody is still active or False if its complete
ALGORITHM: none
NOTES: none
*************************************************************************** */
int PlayMelody(void)
{
int octave = 0;
int duration = 0;
long note = 0;
// Check for a valid Melody
if (Melody_Pointer >= LAST_MELODY)
{
// Reset the Melody to the start
Melody_Pointer = 0;
Note_Index = 0xFFFF;
}
// Load notes while we have enough room
while (Notestat.Count < MAX_NOTE_BUFFER_SIZE)
{
// Is this the first note?
if (Note_Index == 0xFFFF)
{
Tempo = get_tempo();
Note_Index = 0;
}
// Set Default duration
duration = get_defaultduration();
// Set Default Octave
octave = get_defaultoctave();
// Play a bit of slience between notes
if (get_char_from_tune(Note_Index) == ',')
{
PlayNote(0, 4, DURATION_32);
Note_Index++;
return(TRUE);
}
// We are checking the duration
else if ((get_char_from_tune(Note_Index) == '3') && (get_char_from_tune(Note_Index+1) == '2'))
{
duration = DURATION_32;
Note_Index += 2;
}
else if ((get_char_from_tune(Note_Index) == '1') && (get_char_from_tune(Note_Index+1) == '6'))
{
duration = DURATION_16;
Note_Index += 2;
}
else if (get_char_from_tune(Note_Index) == '8')
{
duration = DURATION_8;
Note_Index++;
}
else if (get_char_from_tune(Note_Index) == '4')
{
duration = DURATION_4;
Note_Index++;
}
else if (get_char_from_tune(Note_Index) == '2')
{
duration = DURATION_2;
Note_Index++;
}
else if (get_char_from_tune(Note_Index) == '1')
{
duration = DURATION_1;
Note_Index++;
}
// Now we get the note
switch (get_char_from_tune(Note_Index++))
{
case 'c':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_C_SHARP;
Note_Index++;
}
else
note = NOTE_C;
break;
case 'd':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_D_SHARP;
Note_Index++;
}
else
note = NOTE_D;
break;
case 'e':
note = NOTE_E;
break;
case 'f':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_F_SHARP;
Note_Index++;
}
else
note = NOTE_F;
break;
case 'g':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_G_SHARP;
Note_Index++;
}
else
note = NOTE_G;
break;
case 'a':
if (get_char_from_tune(Note_Index) == '#')
{
note = NOTE_A_SHARP;
Note_Index++;
}
else
note = NOTE_A;
break;
case 'b':
note = NOTE_B;
break;
case 'p': // slience
note = NOTE_SILENCE;
break;
}
// See if this note is 1.5x the duration
if (get_char_from_tune(Note_Index) == '.')
{
// Use the MSB to signify 1.5x
duration |= 0x80;
Note_Index++;
}
// Get the octave
switch (get_char_from_tune(Note_Index))
{
case '4':
octave = 4;
Note_Index++;
break;
case '5':
octave = 5;
Note_Index++;
break;
case '6':
octave = 6;
Note_Index++;
break;
case '7':
octave = 7;
Note_Index++;
break;
default:
break;
}
// Sometimes the duration multiplier comes after the octave
if (get_char_from_tune(Note_Index) == '.')
{
/* Duration 1.5x */
duration |= 0x80;
Note_Index++;
}
// Play the note (we actually just load it in a buffer
PlayNote(note, octave, duration);
// Is this the end?
if (get_char_from_tune(Note_Index) == 0)
{
Note_Index = 0xFFFF;
return(FALSE);
}
}
return(TRUE);
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void PlayNote(long note, int octave, int duration)
{
long duration_count;
// Process octave
switch (octave)
{
case 4 :
break;
case 5 :
note = note >> 1;
break;
case 6 :
note = note >> 2;
break;
case 7 :
note = note >> 4;
break;
}
// Process Note Duration
duration_count = 256;
duration_count >>= (duration & 0x7F);
// If duration is 1.5x add .5 to duration
if (duration & 0x80)
duration_count += (duration_count >> 1);
// Add the note to our buffer
NoteBuffer[Notestat.Tail].note = note;
NoteBuffer[Notestat.Tail].duration = duration_count;
Notestat.Tail++;
Notestat.Tail &= NOTE_ROLLOVER_MASK;
Notestat.Count++;
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void InitTimer(void)
{
setup_timer_0(RTCC_DIV_256 | RTCC_8_BIT);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_CCP1);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_TIMER2);
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
char get_char_from_tune(long index)
{
switch (Melody_Pointer)
{
case SILENTNIGHT:
if (index<127)
return (SilentNight.tune1[index]);
else
return (SilentNight.tune2[index-127]);
break;
case JINGLEBELLS:
if (index<127)
return (JingleBells.tune1[index]);
else
return (JingleBells.tune2[index-127]);
break;
default:
break;
}
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
int get_tempo(void)
{
switch (Melody_Pointer)
{
case SILENTNIGHT:
return (SilentNight.tempo);
break;
case JINGLEBELLS:
return (JingleBells.tempo);
break;
default:
break;
}
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
int get_defaultoctave(void)
{
switch (Melody_Pointer)
{
case SILENTNIGHT:
return (SilentNight.defaultoctave);
break;
case JINGLEBELLS:
return (JingleBells.defaultoctave);
break;
default:
break;
}
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
int get_defaultduration(void)
{
switch (Melody_Pointer)
{
case SILENTNIGHT:
return (SilentNight.defaultduration);
break;
case JINGLEBELLS:
return (JingleBells.defaultduration);
break;
default:
break;
}
}
/* *************************************************************************
DESCRIPTION: This function handles checking for button presses
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void Melody_Task(void)
{
if (PlayMelodyFlag)
{
if (PlayMelody()==0)
Melody_Pointer++;
}
}
//----------------------------------------------------------------------------
// ISR routines
//----------------------------------------------------------------------------
#int_ccp1
/* *************************************************************************
DESCRIPTION: This function controls the PWM of the piezo speaker
RETURN: none
ALGORITHM: none
NOTES: If you do not wish to use C2 as the output, then you will need
to toggle your output here. Make sure that you change the CCP
setup not to toggle the C2 output if this is the case
*************************************************************************** */
void ccp1_isr (void)
{
CCP_1 += Note_Ticks;
#if defined(__PCM__)
output_toggle(PIN_C2);
#endif
}
/* *************************************************************************
DESCRIPTION: This function is used to control the duration of the note
RETURN: none
ALGORITHM: none
NOTES: I store the notes in a buffer so that the main loop has other
time to do stuff with out have to sit at wait for a note to
complete.
*************************************************************************** */
#int_timer0
void timer0_isr (void)
{
// Preload a value for TMR0 so that we can control how long it takes to
// trigger an interrupt
TMR0 = Tempo;
// Is a note playing?
if (DurationCount)
{
DurationCount--;
if (!DurationCount)
setup_ccp1(CCP_OFF);
}
// Note is finished playing, do we have anymore in our buffer?
else if (Notestat.Count)
{
DurationCount = NoteBuffer[Notestat.Head].duration;
Note_Ticks = NoteBuffer[Notestat.Head].note;
Notestat.Count--;
Notestat.Head++;
Notestat.Head &= NOTE_ROLLOVER_MASK;
CCP_1 = TMR1 + Note_Ticks;
if (Note_Ticks)
{
/* Setup the CCP module to toggle the output pin c2 */
#if defined(__PCH__)
setup_ccp1(CCP_COMPARE_TOGGLE_MATCH);
#else
setup_ccp1(CCP_COMPARE_INT);
#endif
}
// Nope, we are all through so disable the PWM
else
{
setup_ccp1(CCP_OFF);
}
}
}