CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

sth confused about MIDI code

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
saroch



Joined: 06 Oct 2004
Posts: 8

View user's profile Send private message Send e-mail MSN Messenger

sth confused about MIDI code
PostPosted: Tue Nov 23, 2004 9:36 am     Reply with quote

I don't know what MIDI code inserted to CCS code be?
I know that MIDI is just a sound that compose of each note C, D, E, ... , B.
but when we hear MIDI ,why we think that song sounds quite good even there are only 7-8 notes !!

so I use PWM to generate pulse to PIC and the data of the code are period and duty cycle.

1. period is 1/frequency of each note, isn't it?
2. duty cycle is used to measure how loud of that sound (50% is loudest) ??
3. how can I set the length of each note (I use for loop to set it)
4. How about MIDI code used to generate good sound like that of downloaded from the internet?

thx in advance
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Nov 23, 2004 10:33 am     Reply with quote

Quote:

1. period is 1/frequency of each note, isn't it?

Yes

Quote:

2. duty cycle is used to measure how loud of that sound (50% is loudest) ??

No. You will get an asymetrical wave. Should be 50%. The loudest is controller by the amplitude of the signal.

Quote:

3. how can I set the length of each note (I use for loop to set it)

Keep the signal on longer

Quote:

4. How about MIDI code used to generate good sound like that of downloaded from the internet?

The output is not a sine wave but rather a square wave. This causes distortion.


Did you get the ring tone code to work? You aren't going to get better sound by using a PWM. In fact, it will be worse because you don't have fine enough resolution with the PWM. What exactly is your goal? What are you trying to do?
Charlie U



Joined: 09 Sep 2003
Posts: 183
Location: Somewhere under water in the Great Lakes

View user's profile Send private message

PostPosted: Tue Nov 23, 2004 2:35 pm     Reply with quote

There's tons of info on the internet about MIDI. Here's just one basic tutorial on MIDI:

http://www.borg.com/~jglatt/tutr/miditutr.htm
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Nov 23, 2004 2:40 pm     Reply with quote

See this orginal post:
http://www.ccsinfo.com/forum/viewtopic.php?t=20949

He orginally wanted a PIC to play a midi file. I think his real goal is just to play some tunes with a PIC which I already gave him some code for.
saroch



Joined: 06 Oct 2004
Posts: 8

View user's profile Send private message Send e-mail MSN Messenger

PostPosted: Wed Nov 24, 2004 10:45 am     Reply with quote

Hi,

My real goal is to play a song from PIC.
It could be MIDI or WAV but I think MIDI uses fewer memory than WAV.
So I decide to use MIDI rather than WAV.
(PIC has only 256K memory !! If I use WAV I must require more memory that make more expenses for my project)

But If I use MIDI, I really want quite good quality sound at least you should not bore while hearing it for a ling time.
In addition, I want to play that MIDI and lengthen or shorten it at anytime.
Because of these, the problem I encounter is

1. How can I play a quite good quality MIDI ?
2. What is that MIDI code that I might insert it to my code and where to find them ?
3. How can I lengthen or shorten them at anytime I want

Here is my code that based on Mark's code.
I can understand your code slightly so that I don't know how to insert which type of "MIDI code" to my code.
So I don't know what code of Happy Birthday Song to put in my code.

Code:

#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#define CLOCKSPEED 20000000
#use delay(clock=CLOCKSPEED)

#define PRESCALE       16
#define NOTE_C         (((CLOCKSPEED/4)/2093)/PRESCALE)-1      //148.31
#define NOTE_D         (((CLOCKSPEED/4)/2349)/PRESCALE)-1      //132.04
#define NOTE_E         (((CLOCKSPEED/4)/2637)/PRESCALE)-1      //117.51
#define NOTE_F         (((CLOCKSPEED/4)/2794)/PRESCALE)-1      //110.85
#define NOTE_G         (((CLOCKSPEED/4)/3136)/PRESCALE)-1      //98.65
#define NOTE_A         (((CLOCKSPEED/4)/3520)/PRESCALE)-1      //87.78
#define NOTE_B         (((CLOCKSPEED/4)/3951)/PRESCALE)-1      //78.09

void main()
{
   char mysong[27] = {'E','D','C','D','E','E','E','D','D','D','E','G','G','S','E','D','C','D','E','E','E','C','D','D','E','D','C'};
   char note;
   int i;
   int16 j;

   setup_ccp1(CCP_PWM);

   while(1)
   {
      for (i=0;i<=26;i++)
      {
         note=mysong[i];
         switch (note)
         {
         case 'C' :
               for (j=1;j<300;j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_C, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*2093)));
               delay_ms(1);
               }
               break;
         case 'D' :
               for (j=1;j<300;j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_D, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*2349)));
               delay_ms(1);
               }
               break;
         case 'E' :
               for (j=1;j<300;j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_E, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*2637)));
               delay_ms(1);
               }
               break;
         case 'F' :
               for (j=1;j<300;j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_F, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*2794)));
               delay_ms(1);
               }
               break;
         case 'G' :
               for (j=1;j<300;j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_G, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*3136)));
               delay_ms(1);
               }
               break;
         case 'A' :
               for (j=1;j<300;j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_A, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*3520)));
               delay_ms(1);
               }
               break;
         case 'B' :
               for (j=1;j<300;j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_B, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*3951)));
               delay_ms(1);
               }
               break;
         case 'S' :
               for (j=1;j<300;j++)
               {
               delay_ms(1);
               }
               break;
         }
      }
   }
}


And the last question
I know that PIC16F877 has prescaler max to 16 and if I use XTal 20 MHz, I can't make a calcution to give a frequency of 440 MHz (frequency of "A" note)
I decide to use 4 MHz instead that can support that low frequency but I'm confused why you can use 20 MHz to produce 440 MHz ?

thank you everyone in advance,
Saroch
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Nov 24, 2004 11:34 am     Reply with quote

Quote:
but I'm confused why you can use 20 MHz to produce 440 MHz ?


That is because I didn't use the PWM. That is what I was referring to by

Quote:
In fact, it will be worse because you don't have fine enough resolution with the PWM.



I am just using the CCP int so I can control the note with very fine resolution.

Quote:
PIC has only 256K memory !!

Better check again. The PIC16F877 only has 8K of memory (14 bits wide) and 256 bytes of eeprom.

Quote:
So I don't know what code of Happy Birthday Song to put in my code

Piece of cake with the RingTone program.

Did you ever get my program to work?
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Nov 24, 2004 12:31 pm     Reply with quote

Quote:

So I don't know what code of Happy Birthday Song to put in my code.


Here is a happy birthday song I found on the web (ringtone) in 2 different formats.
d=4 -> default duration
0=5 -> default octave
b=125 -> tempo

I included both formats so that you could compare the two. The main difference is - & p. These are silence

The octaves are a bit different as well. The Nokring uses 4,5,6,7 (as does the code) while the composer form starts at 1.

Quote:

Nokring / RTTL
bday:d=4,o=5,b=125:16c,32p,32c,32p,8d,32p,8c,32p,8f,32p,e,16p,16c,32p,
32c,32p,8d,32p,8c,32p,8g,32p,f,8p,16c,32p,32c,32p,8c6,32p,8a,32p,8f,32p,
8e,32p,8d,32p,16a#,32p,32a#,32p,8a,32p,8f,32p,8g,32p,f



Quote:
Nokia Composer Code
Tempo 125
16c1 32- 32c1 32- 8d1 32- 8c1 32- 8f1 32- 4e1 16- 16c1 32- 32c1 32- 8d1 32- 8c1 32- 8g1 32- 4f1 8- 16c1 32- 32c1 32- 8c2 32- 8a1 32- 8f1 32- 8e1 32- 8d1 32- 16#a1 32- 32#a1 32- 8a1 32- 8f1 32- 8g1 32- 4f1


And here is how I would put it in my code
Code:

const struct
{
  char tune1[128];
  char tune2[54];
  int  defaultoctave;
  int  defaultduration;
  int  tempo;
}HappyBirthday = {
                 {"16c,32p,32c,32p,8d,32p,8c,32p,8f,32p,e,16p,16c,32p,32c,32p,8d,32p,8c,32p,8g,32p,f,8p,16c,32p,32c,32p,8c6,32p,8a,32p,8f,32p,8e,3"},
                 {"2p,8d,32p,16a#,32p,32a#,32p,8a,32p,8f,32p,8g,32p,f,1p"},
                 5,
                 DURATION_4,
                 125
               };


Another thing I would like to point out about my code. It appears a bit more complex than it could be. It was ported over from some code I wrote for the C18 compiler which allowed pointers to const. Also, the code uses "tasks" so that songs can be played during the background of an application. I orginally wrote this for a Christmas presentation where our products were used in a Christmas theme scene. It was in one of our lighting controllers and actually blinked the lights to the tune of the music.
Tuned
Guest







PostPosted: Wed Nov 24, 2004 2:02 pm     Reply with quote

I tried the code you posted before and the function
Code:

output_toggle(PIN_C2);

is not recognized by the compiler or is not defined previously.

Whatversion of ccs compiler should I use to fix this problem or where is that function defined?

Thanks
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Nov 24, 2004 4:50 pm     Reply with quote

Well, the latest version has it. If not, then you can do it like this

Code:

static BOOLEAN state = 0;

state = !state;
if (state)
  output_high(PIN_C2);
else
  output_low(PIN_C2);
saroch



Joined: 06 Oct 2004
Posts: 8

View user's profile Send private message Send e-mail MSN Messenger

PostPosted: Thu Nov 25, 2004 11:16 am     Reply with quote

Hi, Mark
For your code can I lengthen or shorten it ?

I mean if I want the song longer and shorter.
What kind of delay can be used ?

thx
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Nov 25, 2004 12:27 pm     Reply with quote

The song is just a bunch of notes. Can it be longer, sure. Can it be shorter, sure. It supports 4 octaves. The note duration can be changed in the string. That's what the number in front of the note is. It even supports 1.5 times the duration by using a "." You can make it do whatever you want. The key to the code is how it generates the notes. I don't think you will find a better solution without using some sort of specialized IC or a DAC.
Guest








PostPosted: Fri Nov 26, 2004 1:27 am     Reply with quote

Hi, Mark

I used this code but it can't compile completely.
I don't realize that why it is happened.

Here is my code.
Code:

#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#define CLOCKSPEED 4000000
#use delay(clock=CLOCKSPEED)

#define use_portb_lcd
#include <Lcd.c>

#define PRESCALE       16

#define NOTE_C         ((int)(((CLOCKSPEED/4)/261.63)/PRESCALE)-1)
#define NOTE_D         ((int)(((CLOCKSPEED/4)/293.66)/PRESCALE)-1)
#define NOTE_E         ((int)(((CLOCKSPEED/4)/329.63)/PRESCALE)-1)
#define NOTE_F         ((int)(((CLOCKSPEED/4)/349.23)/PRESCALE)-1)
#define NOTE_G         ((int)(((CLOCKSPEED/4)/392.00)/PRESCALE)-1)
#define NOTE_A         ((int)(((CLOCKSPEED/4)/440.00)/PRESCALE)-1)
#define NOTE_B         ((int)(((CLOCKSPEED/4)/493.88)/PRESCALE)-1)

#define NOTE_C_SHARP   ((int)(((CLOCKSPEED/4)/277.18)/PRESCALE)-1)
#define NOTE_D_SHARP   ((int)(((CLOCKSPEED/4)/311.13)/PRESCALE)-1)
#define NOTE_F_SHARP   ((int)(((CLOCKSPEED/4)/369.99)/PRESCALE)-1)
#define NOTE_G_SHARP   ((int)(((CLOCKSPEED/4)/415.30)/PRESCALE)-1)
#define NOTE_A_SHARP   ((int)(((CLOCKSPEED/4)/466.16)/PRESCALE)-1)

void play_song(int duration);
void play(char note, char length, int duration);

void main()
{
   lcd_init();
   int duration = 10;
   play_song(duration);
}

void play_song(int duration)
{
   char mysong[2][7]=
   {
      {'E','D','C','D','E','E','E'},
      {'5','1','1','1','1','1','1'}   
   };

   char note,length;
   int i,j;

   setup_ccp1(CCP_PWM);

   for(j=0;j<=6;j++)
   {
      note=mysong[0][j];
      length=mysong[1][j];

      play(note,length,duration);
   }   
}

void play(char note, char length, int duration)
{
   int16 j;
   int length2;
   length2 = (int)length-48;
   
   lcd_gotoxy(1,1);
   printf(lcd_putc,"%c",note);
   delay_ms(1500);
   printf(lcd_putc,"%i",length2);
   delay_ms(1500);

         switch (note)
         {
         case 'C' :
               for (j=1;j<(100*length2);j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_C, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*261.63)));
               delay_ms(1);
               }
               break;
         case 'D' :
               for (j=1;j<(100*length2);j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_D, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*293.66)));
               delay_ms(1);
               }
               break;
         case 'E' :
               for (j=1;j<(100*length2);j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_E, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*329.63)));
               delay_ms(1);
               }
               break;
         case 'F' :
               for (j=1;j<(100*length2);j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_F, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*349.23)));
               delay_ms(1);
               }
               break;
         case 'G' :
               for (j=1;j<(100*length2);j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_G, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*392.00)));
               delay_ms(1);
               }
               break;
         case 'A' :
               for (j=1;j<(100*length2);j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_A, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*440.00)));
               delay_ms(1);
               }
               break;
         case 'B' :
               for (j=1;j<(100*length2);j++)
               {
               setup_timer_2(T2_DIV_BY_16, NOTE_B, 1);
               set_pwm1_duty((int)(CLOCKSPEED/(PRESCALE*2*493.88)));
               delay_ms(1);
               }
               break;
         case 'S' :
               for (j=1;j<(100*length2);j++)
               {
               setup_timer_2(T2_DIV_BY_16, 0, 1);
               delay_ms(1);
               }
               break;
         }
   
   for (j=1;j<(100*duration);j++)
      {
      setup_timer_2(T2_DIV_BY_16, 0, 1);
      delay_ms(1);
      }
}


There is an error on lcd_init(); line.

But another problem is that I can't lengthen or shorten it what I want.
Because length is defined as char, but It should be an integer when used so I change that char to integer by converting it to int and subtract 48. (by using ascii table)
But when I hear the sound, it doesn't lengthen or shorten what it should be.

Code:

void play(char note, char length, int duration)
{
   int16 j;
   int length2;
   length2 = (int)length-48;
   
   .............................

jane
Guest







PostPosted: Sun Nov 28, 2004 10:36 am     Reply with quote

Sorry, I can't correct them.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Sun Nov 28, 2004 10:56 am     Reply with quote

Quote:
I used this code but it can't compile completely.


The code you posted is not anything like my code. See the link I posted for the correct code.

Quote:
Because length is defined as char, but It should be an integer when used so I change that char to integer by converting it to int and subtract 48


char and int are the same data type for this compiler. Furthermore, char doesn't mean that the data is a "character" but rather it is an 8bit unsigned value.

Code:

char x;
int y;

x = 8
y = 8;


x and y are equal in CCS. Now if you said
Code:

x = '8'
y = 8;

Then they would be different but there is nothing stopping you from doing this either
Code:

x = '8'
y = '8';


Clear as mudd?



Quote:
Sorry, I can't correct them.

I would suggest you register. It is free you know. Then we would know which posts are yours instead of being guest or jane because your statement makes no sense to me at all. You can't correct what?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group