![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
saroch
Joined: 06 Oct 2004 Posts: 8
|
sth confused about MIDI code |
Posted: Tue Nov 23, 2004 9:36 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Nov 23, 2004 10:33 am |
|
|
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? |
|
![](templates/subSilver/images/spacer.gif) |
Charlie U
Joined: 09 Sep 2003 Posts: 183 Location: Somewhere under water in the Great Lakes
|
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Nov 23, 2004 2:40 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
saroch
Joined: 06 Oct 2004 Posts: 8
|
|
Posted: Wed Nov 24, 2004 10:45 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Nov 24, 2004 11:34 am |
|
|
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? |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Nov 24, 2004 12:31 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Tuned Guest
|
|
Posted: Wed Nov 24, 2004 2:02 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Nov 24, 2004 4:50 pm |
|
|
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);
|
|
|
![](templates/subSilver/images/spacer.gif) |
saroch
Joined: 06 Oct 2004 Posts: 8
|
|
Posted: Thu Nov 25, 2004 11:16 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Thu Nov 25, 2004 12:27 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Fri Nov 26, 2004 1:27 am |
|
|
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;
.............................
|
|
|
![](templates/subSilver/images/spacer.gif) |
jane Guest
|
|
Posted: Sun Nov 28, 2004 10:36 am |
|
|
Sorry, I can't correct them. |
|
![](templates/subSilver/images/spacer.gif) |
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Nov 28, 2004 10:56 am |
|
|
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
Then they would be different but there is nothing stopping you from doing this either
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? |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|