TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: septiembre_negro en 13 de Octubre de 2009, 23:17:04

Título: Notas musicales
Publicado 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
Título: Re: Notas musicales
Publicado por: MLO__ en 13 de Octubre de 2009, 23:25:12
Hola.

Como asi que te genere?

Si tienes la partitura, posteala y yo te la paso a las notas, eso no es complicado.
Título: Re: Notas musicales
Publicado por: septiembre_negro en 14 de Octubre de 2009, 14:21:08
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


Título: Re: Notas musicales
Publicado por: MLO__ en 14 de Octubre de 2009, 15:11:22
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
Título: Re: Notas musicales
Publicado por: nicola en 14 de Octubre de 2009, 16:35:57
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...
Título: Re: Notas musicales
Publicado por: septiembre_negro en 14 de Octubre de 2009, 18:29:42
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.

Título: Re: Notas musicales
Publicado por: septiembre_negro en 14 de Octubre de 2009, 18:35:12
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  :-/ :-/

Título: Re: Notas musicales
Publicado por: septiembre_negro en 14 de Octubre de 2009, 19:05:47
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|------------------|-------------------|-----------------|----------------||

Título: Re: Notas musicales
Publicado por: MLO__ en 14 de Octubre de 2009, 23:08:53
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
Título: Re: Notas musicales
Publicado por: septiembre_negro en 15 de Octubre de 2009, 13:15:38
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
Título: Re: Notas musicales
Publicado por: MLO__ en 15 de Octubre de 2009, 14:03:06
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
Título: Re: Notas musicales
Publicado por: jhozate en 15 de Octubre de 2009, 14:18:27
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
Título: Re: Notas musicales
Publicado por: nicola en 15 de Octubre de 2009, 14:21:45
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
Título: Re: Notas musicales
Publicado por: septiembre_negro en 15 de Octubre de 2009, 16:09:07
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
Título: Re: Notas musicales
Publicado por: MLO__ en 15 de Octubre de 2009, 19:50:54
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
Título: Re: Notas musicales
Publicado por: septiembre_negro en 15 de Octubre de 2009, 21:30:23
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

Código: [Seleccionar]

/*                                                                           */
/*            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);
    }
  }
}
Título: Re: Notas musicales
Publicado por: MLO__ en 15 de Octubre de 2009, 22:03:55
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
Título: Re: Notas musicales
Publicado por: septiembre_negro en 16 de Octubre de 2009, 14:43:38
Ok boy a investigar mas afondo el código rtttl.  es una pena que el ejemplo que encontré este tan enredado. :( :(
saludos
Título: Re: Notas musicales
Publicado por: septiembre_negro en 16 de Octubre de 2009, 23:01:07
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
 
Título: Re: Notas musicales
Publicado por: septiembre_negro en 16 de Octubre de 2009, 23:05:28
Este es el código rtttl que tome para el ejercicio:
Código: [Seleccionar]
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



Código: [Seleccionar]
////                                                                 ////
////  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);
      }
   }
}
Título: Re: Notas musicales
Publicado por: MLO__ en 17 de Octubre de 2009, 00:04:09
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
Título: Re: Notas musicales
Publicado por: septiembre_negro en 17 de Octubre de 2009, 14:25:45
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
Título: Re: Notas musicales (Resuelto)
Publicado por: septiembre_negro en 18 de Octubre de 2009, 14:41:59
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

Título: Re: Notas musicales
Publicado por: Cryn en 18 de Octubre de 2009, 22:03:11
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.
Título: Re: Notas musicales
Publicado por: septiembre_negro en 19 de Octubre de 2009, 14:51:16
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.

Título: Re: Notas musicales
Publicado por: septiembre_negro en 19 de Octubre de 2009, 15:06:00
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 :
Código: [Seleccionar]
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:

Código: [Seleccionar]

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

Título: Re: Notas musicales
Publicado por: septiembre_negro en 19 de Octubre de 2009, 15:16:50
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;
}

Título: Re: Notas musicales
Publicado por: septiembre_negro en 19 de Octubre de 2009, 15:32:35
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

Título: Re: Notas musicales
Publicado por: Cryn en 20 de Octubre de 2009, 18:36:54
 :shock: guau cuanta info, ya tengo para rato

muchas gracias septiembre_negro :-/
Título: Re: Notas musicales
Publicado por: septiembre_negro en 21 de Octubre de 2009, 14:30:25
Pues que te diviertas  8) ;-) y si alguien encuentra como resolver lo de convertir midi a rtttl que pegue un  grito   :?
Título: Re: Notas musicales
Publicado por: septiembre_negro en 24 de Octubre de 2009, 15:45:44
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.

Título: Re: Notas musicales
Publicado por: septiembre_negro en 25 de Octubre de 2009, 17:01:26
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]
Título: Re: Notas musicales
Publicado por: MLO__ en 26 de Octubre de 2009, 15:24:37
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
Título: Re: Notas musicales
Publicado por: micro_cadaver en 02 de Noviembre de 2009, 16:30:55
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.
Título: Re: Notas musicales
Publicado por: septiembre_negro en 02 de Noviembre de 2009, 17:00:00
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
Título: Re: Notas musicales
Publicado por: septiembre_negro en 02 de Noviembre de 2009, 17:10:16
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
Título: Re: Notas musicales
Publicado por: micro_cadaver en 02 de Noviembre de 2009, 20:24:11
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?
Título: Re: Notas musicales
Publicado por: septiembre_negro en 02 de Noviembre de 2009, 21:39:10
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
Título: Re: Notas musicales
Publicado por: micro_cadaver en 03 de Noviembre de 2009, 00:50:05
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.
Título: Re: Notas musicales
Publicado por: MLO__ en 03 de Noviembre de 2009, 10:56:41
 ;-)

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
Título: Re: Notas musicales
Publicado por: micro_cadaver en 03 de Noviembre de 2009, 13:01:14
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
Título: Re: Notas musicales
Publicado por: septiembre_negro en 03 de Noviembre de 2009, 17:02:29
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.

Título: Re: Notas musicales
Publicado por: septiembre_negro en 03 de Noviembre de 2009, 17:09:26
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


Código: [Seleccionar]


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






             
     
Título: Re: Notas musicales
Publicado por: micro_cadaver en 03 de Noviembre de 2009, 17:47:11
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.
Título: Re: Notas musicales
Publicado por: MLO__ en 03 de Noviembre de 2009, 23:18:29
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
Título: Re: Notas musicales
Publicado por: MLO__ en 04 de Noviembre de 2009, 00:05:56
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:

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í:

Citar
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á
Título: Re: Notas musicales
Publicado por: micro_cadaver en 04 de Noviembre de 2009, 01:32:13
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  :-/
Título: Re: Notas musicales
Publicado por: septiembre_negro en 04 de Noviembre de 2009, 19:02:29
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)
Título: Re: Notas musicales
Publicado por: micro_cadaver en 04 de Noviembre de 2009, 19:12:45
añap, entonces manos a la obra, en la noche posteare una idea que tengo del software para exportar los archivos canciones.c

saludos  :-/
Título: Re: Notas musicales
Publicado por: MLO__ en 05 de Noviembre de 2009, 00:28:52
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:

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
Título: Re: Notas musicales
Publicado por: micro_cadaver en 05 de Noviembre de 2009, 03:28:18
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.  :-/
Título: Re: Notas musicales
Publicado por: MLO__ en 05 de Noviembre de 2009, 11:18:29
 :)

que envidia hombre .....
Título: Re: Notas musicales
Publicado por: micro_cadaver en 05 de Noviembre de 2009, 13:31:20
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!!!
Título: Re: Notas musicales
Publicado por: MLO__ en 05 de Noviembre de 2009, 13:38:31
 ;-)

Pues voy a estar por Ica desde el 19 al 27 de Noviembre .... podria hacerse algo no? jejejeje
Título: Re: Notas musicales
Publicado por: septiembre_negro en 05 de Noviembre de 2009, 15:30:57
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
Título: Re: Notas musicales
Publicado por: septiembre_negro en 05 de Noviembre de 2009, 15:34:49
;-)

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:
Título: Re: Notas musicales
Publicado por: micro_cadaver en 05 de Noviembre de 2009, 16:22:10
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!!!



Título: Re: Notas musicales
Publicado por: septiembre_negro en 05 de Noviembre de 2009, 16:40:44
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
Título: Re: Notas musicales
Publicado por: micro_cadaver en 05 de Noviembre de 2009, 17:10:24
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.  :-/ :-/
Título: Re: Notas musicales
Publicado por: micro_cadaver en 06 de Noviembre de 2009, 12:12:13
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.  :-/ :-/
Título: Re: Notas musicales
Publicado por: septiembre_negro en 06 de Noviembre de 2009, 16:31:24
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
Título: Re: Notas musicales
Publicado por: micro_cadaver en 06 de Noviembre de 2009, 16:41:46
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.
Título: Re: Notas musicales
Publicado por: septiembre_negro en 06 de Noviembre de 2009, 17:51:30
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.
Título: Re: Notas musicales
Publicado por: micro_cadaver en 06 de Noviembre de 2009, 17:59:58
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...
Título: Re: Notas musicales
Publicado por: MLO__ en 06 de Noviembre de 2009, 20:21:28
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
Título: Re: Notas musicales
Publicado por: micro_cadaver en 07 de Noviembre de 2009, 01:28:34
entonces antes de continuar con el soft, algun aporte más, algo que le falte o asi queda?

Título: Re: Notas musicales
Publicado por: septiembre_negro en 07 de Noviembre de 2009, 17:45:50
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í
Código: [Seleccionar]
#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};

Título: Re: Notas musicales
Publicado por: principal1414 en 17 de Noviembre de 2013, 18:36:39
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

Código: [Seleccionar]

/*                                                                           */
/*            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);
    }
  }
}