Go Down

Topic: "Melody" Example "dies" halfway (Read 3656 times) previous topic - next topic

toxto

Hi guys and ladies!

I bought a Duemilanove (ATM 328) yesterday.

I connected a little piezzo speaker to it. It worked fine.

I uploaded the basic "Melody" example, it worked fine. I changed note lenghts and stuff, it worked fine.

I added new notes to the basic ones and used them and it worked.

Then i started to "compose" the legendary Beatles "Let It Be" tune on it. I added some notes, uploaded, tried. It worked fine till a point.

Now i have 56 notes but the "Duemila" "freezes" about halfway in the tune, it just puts out a low note constatly (after played about half of the notes) till i turn it off.

The code compiles fine. It uses only 1798 bytes from the 30k.

Here's the code:

Code: [Select]
int speakerPin = 9;

int length = 56; // the number of notes
char notes[] = "ggaeggCDEEEDDCC gEEFEED EDDC EDCEGAGGEDCagE EEEFEED EDDC"; // a space represents a rest
int beats[] = { 2, 1, 2, 2, 3, 2, 1, 2, 1, 1, 4, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 1, 1, 1, 1, 2, 2, 8, 1, 2, 5, 1, 2, 5, 1, 1, 1, 1, 4, 1, 2, 5, 5, 1, 1, 1, 2, 1, 1, 4, 1, 1, 1, 2, 2};
int tempo = 200;

void playTone(int tone, int duration) {
 for (long i = 0; i < duration * 1000L; i += tone * 2) {
   digitalWrite(speakerPin, HIGH);
   delayMicroseconds(tone);
   digitalWrite(speakerPin, LOW);
   delayMicroseconds(tone);
 }
}

void playNote(char note, int duration) {
 char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'D', 'E', 'F', 'G', 'A', 'B' };
 int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956, 851, 760, 716, 628, 568, 507 };
 
 // play the tone corresponding to the note name
 for (int i = 0; i < 56; i++) {
   if (names[i] == note) {
     playTone(tones[i], duration);
   }
 }
}

void setup() {
 pinMode(speakerPin, OUTPUT);
}

void loop() {
 for (int i = 0; i < length; i++) {
   if (notes[i] == ' ') {
     delay(beats[i] * tempo); // rest
   } else {
     playNote(notes[i], beats[i] * tempo);
   }
   
   // pause between notes
   delay(tempo / 2);
 }
}


There is a hardware limit somewhere? It can play only about 25 notes? I fucked up something bad?

Thanks for the answers. ;)

SteelToad

in playNote

 for (int i = 0; i < 56; i++) {

should be

 for (int i = 0; i < 14; i++) {

You only have 14 notes, so your probably comparing, and matching some random value past the end of your names or tones arrays

toxto

Thanks, i tried it, you are right ;D

The problem was the fact that i know nothing about the "for" command (and about C generally :D) so at first when i added the first notes i noticed that it doesn't play them. So i started adding the number of the plus notes to every sensible number i saw. It worked till halfway. ;)

Thanks again, it works now. I feel like Mozart. Or more like McCartney. ::)

However i have an other question. Can you "define" notes with names which are longer than 1 character? You know like F# or Db. Because this way i can name only 2 octave normally. (1 octave: without caps lock. 2 octave: with capslock) Plus this way i can only use notes from the C Major scale (CDEFGABC)

I feel like a lion in a cage with only two octaves and with C major scale only. ;D

potatohead

Perhaps you should have started out with Bill Haley and the Comets, then worked your way 'up' to the Beatles.

Oh, sorry; ...humor.  :-[

Pakk

toxto

;D

Well actually, if i won't find any other way to name notes, (apart from name them from other characters like "A#"="y" and so on) so i should stick to C major key, i will still have a huge advantage over a lot of todays "artists" by actually being able to stay in key. ;D

halley

#5
Apr 17, 2009, 09:15 pm Last Edit: Apr 17, 2009, 09:16 pm by halley Reason: 1
If you're not sure how to denote music in string form, I suggest you read the following article:  http://en.wikipedia.org/wiki/Music_macro_language

Unlike the Melody example, this "music macro language" has existed for well over twenty years, since long before MIDI, and I've seen implementations that add all sorts of neat little extras without breaking the main syntax.

If I wasn't so darn lazy and engaged in other projects, I'd implement the language in an Arduino myself, it could easily be done in less than 200 lines of C.

SteelToad

These changes should allow for sharp frequencies, and allow you to put the # after a note. I just put in dummy values because I have no idea of the correct numbers.  

This plays each character (skipping the '#'s), it still tries to play non-note chars, but playNote just waits for duration if the char isn't a valid note

Code: [Select]

void playNote(char note, boolean sharp, int duration)
 {
 boolean foundnote = false;  // assume an invalid note char
 char names[14] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C', 'D', 'E', 'F', 'G', 'A', 'B' };
 int tones[14] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956, 851, 760, 716, 628, 568, 507 };
 int sharps[14] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
 
 // play the tone corresponding to the note name
 for (int i = 0; i < 14; i++)
   {
   if (names[i] == note)
     {
     foundnote = true; // the note char was valid
     if (sharp)
       playTone(sharps[i], duration);
     else
       playTone(tones[i], duration);
     }
   }
 if (!foundnote) // it wasnt a real note, wait quietly for duration
   delay(duration);
 }


void loop()
 {
 boolean issharp = true;
 int i = 0;
 
 while (i < length)
   {
   issharp = (i < length-1 && notes[i+1] == '#');
   playNote(notes[i], issharp, beats[i] * tempo);
   if (issharp) i += 1;  // skip an extra char to jump past the #
   i += 1; // next char in notes
   }
 }

Go Up