not understanding this code
JR_301
Posts: 22
' What's a Microcontroller - music_with_more_features.bs2 ' Play the first seven notes from Twinkle Twinkle Little Star. ' {$STAMP BS2} ' {$PBASIC 2.5} DEBUG "program running" notes DATA "C","E","E","E","D","E","F","E","E","D","D", "D","C","D","E","C","Q" octaves DATA 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 durations DATA 4, 2, 4, 4, 4, 4, 2, 2, 4, 2, 4, 4, 4, 4, 2, 2 dots DATA 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0 beatspermin CON 320 index VAR Byte offset VAR Nib noteletter VAR Byte notefreq VAR Word noteduration VAR Word noteoctave VAR Nib notedot VAR Word wholenote VAR Word wholenote = 6000 / beatspermin * 4 DO UNTIL noteletter = "Q" READ notes + index, noteletter LOOKDOWN noteletter, [noparse][[/noparse] "C","d","D","e","E", "F","g","G","a","A", "b","B","P","Q" ], offset LOOKUP offset, [noparse][[/noparse] 4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902, 0, 0 ], notefreq READ octaves + index, noteoctave noteoctave = 8 - noteoctave notefreq = notefreq / (DCD noteoctave) READ durations + index, noteduration noteduration = wholenote / noteduration READ dots + index, notedot IF notedot = 1 THEN noteduration = noteduration * 3/2 FREQOUT 9, noteduration, notefreq index = index + 1 LOOP END
When i say im not understanding it, im not understanding VISUALLY how its working.
READ octaves + index, noteoctave noteoctave = 8 - noteoctave notefreq = notefreq / (DCD noteoctave)
For instance, could someone show me how that is running in a "simplistic form"?
Comments
The example you are referring to demonstrates how to take sheet music and play it through the BASIC Stamp. When reading sheet music there are 4 main things to look at:
- What notes you're playing
- The octave you're playing them in (if you look at a piano, one group of C-B keys are considered an octave)
- The tempo of the song (how many beats per measure)
- Any dotted notes which add an additional beat
These four things are saved to EEPROM at the beginning of the program. Since the BASIC Stamp works in milliseconds and not beats per measure, like sheet music does, the number a milliseconds a whole note will last is calculated in the beatspermin variable. In this case, a whole note will last 75 ms.
The rest of the program then cycles through the previously defined DATA directives. Let's take the seventh note as an example, since it covers all matters of sin (so to speak): the note F in the 7th octave, lasting a half note with a dot.
First the program takes the ASCII character "F" through the LOOKDOWN and LOOKUP tables, see that it's corresponding frequency is 5588. However, keep in mind that this number is in the 8th octave (see page 242 of What's a Microcontroller for further explanation).
Now, as stated before, the note "F" is supposed to be played in the 7th octave, which corresponds to a frequency of 2793 (page 239 of What's a Micrcontroller). You may notice that a frequency of 2794 is half of the current frequency of the note F in octave 8, 5588. While this is one higher than the defined frequency of 2793, it can be assumed that if you want to go down an octave, you divide the current frequency by 2. This is what this part of the code does, but instead of just dividing by 2, the result is kept in terms of the 8th octave. Why? What if you wanted to play the note "F" in the 6th octave? Dividing by 2 won't give you the correct frequency anymore, but if you divide by 4 you will get the correct frequency (1397). Here's how it works:
- First, the code reads the current octave from EEPROM and stores it in the variable noteoctave. (In this example, octave 7)
- It then takes that value and subtracts it from 8. (8 - 7 = 1)
- Then, using the DCD operator, the new notefreq is equal to 5588 / (2 ^ 1) = 2794 (See page 242 of What's a Microcontroller for further explanation)
((Side note: If you wanted to play the note "F" in the 6th octave, you would need a frequency of 1397, so 8 - 6 = 2, and 5588 / (2 ^ 2) = 1397. The process can be used for octaves 5-8, which is why we keep it in terms of the 8th octave.))
Next, the program calculates how many milliseconds for the note to last. In this case, it's a half note. Since a whole note lasts 75 ms, a half note will last 75/2 ms:
The next section checks if the note has a dot, which, in sheet music adds half to the current note's duration. So in this case, notedot = 1, noteduration is multiplied by (3/2) to add that extra half.
Finally, the current noteduration and frequency is played through the piezospeaker and then the code moves on to the next note.
I apologize for the lengthy explanation, but playing sheet music through the piezospeaker is a fairly complicated and time consuming task. Maybe we'll just have to feature doing so in an upcoming Project of the Week. [noparse];)[/noparse]
Please let me know if you need any further clarification.
Jessica
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jessica Uelmen
Education Department
Parallax, Inc.
lol, this right here nailed it perfectly! huge thanks