Autor Tema: Notas musicales  (Leído 39719 veces)

0 Usuarios y 2 Visitantes están viendo este tema.

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #15 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);
    }
  }
}
« Última modificación: 15 de Octubre de 2009, 21:34:28 por septiembre_negro »

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Notas musicales
« Respuesta #16 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
El papel lo aguanta todo

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #17 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

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #18 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
 
« Última modificación: 16 de Octubre de 2009, 23:08:31 por septiembre_negro »

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #19 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);
      }
   }
}

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: Notas musicales
« Respuesta #20 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
El papel lo aguanta todo

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #21 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

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales (Resuelto)
« Respuesta #22 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


Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Notas musicales
« Respuesta #23 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.
.

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #24 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.

« Última modificación: 19 de Octubre de 2009, 15:08:55 por septiembre_negro »

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #25 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);
  
   }
}

« Última modificación: 19 de Octubre de 2009, 15:13:08 por septiembre_negro »

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #26 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;
}


Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #27 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


Desconectado Cryn

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4169
Re: Notas musicales
« Respuesta #28 en: 20 de Octubre de 2009, 18:36:54 »
 :shock: guau cuanta info, ya tengo para rato

muchas gracias septiembre_negro :-/
.

Desconectado septiembre_negro

  • PIC18
  • ****
  • Mensajes: 310
Re: Notas musicales
« Respuesta #29 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   :?


 

anything