Open tahunus opened 1 year ago
Perhaps adding the code files here can assist in a visual tour.
const byte buzzPin = 12;
const byte buzzChan = 0;
#include "tunes.h"
int tempo, notes, wholenote, divider, thisNote, noteDuration;
byte activeTune;
bool tuneIsOn, noteIsOn;
ulong elapsedNote;
void defineTunes() {
switch (activeTune) {
case 0: tempo = 190; notes = sizeof(superMarioShort) / sizeof(superMarioShort[0]) / 2; break;
case 1: tempo = 170; notes = sizeof(darthVaderShort) / sizeof(darthVaderShort[0]) / 2; break;
case 2: tempo = 170; notes = sizeof(pinkPantherShort) / sizeof(pinkPantherShort[0]) / 2; break;
case 3: tempo = 190; notes = sizeof(superMarioFull) / sizeof(superMarioFull[0]) / 2; break;
case 4: tempo = 170; notes = sizeof(darthVaderFull) / sizeof(darthVaderFull[0]) / 2; break;
case 5: tempo = 170; notes = sizeof(pinkPantherFull) / sizeof(pinkPantherFull[0]) / 2; break;
case 6: tempo = 140; notes = sizeof(happybirthday) / sizeof(happybirthday[0]) / 2; break;
case 7: tempo = 114; notes = sizeof(odetojoy) / sizeof(odetojoy[0]) / 2; break;
case 8: tempo = 122; notes = sizeof(lionsleeps) / sizeof(lionsleeps[0]) / 2; break;
case 9: tempo = 76; notes = sizeof(brahmslullaby) / sizeof(brahmslullaby[0]) / 2; break;
}
wholenote = (60000 * 4) / tempo; //calculate the duration of a whole note in ms
thisNote = 0;
tuneIsOn = true;
noteIsOn = false;
}
void chkOnTunes() {
if (thisNote < notes * 2) { // for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {
if (!noteIsOn) { // calculates the duration of each note
switch (activeTune) { //array is twice the number of notes (notes + durations)
case 0: divider = superMarioShort[thisNote + 1]; break;
case 1: divider = darthVaderShort[thisNote + 1]; break;
case 2: divider = pinkPantherShort[thisNote + 1]; break;
case 3: divider = superMarioFull[thisNote + 1]; break;
case 4: divider = darthVaderFull[thisNote + 1]; break;
case 5: divider = pinkPantherFull[thisNote + 1]; break;
case 6: divider = happybirthday[thisNote + 1]; break;
case 7: divider = odetojoy[thisNote + 1]; break;
case 8: divider = lionsleeps[thisNote + 1]; break;
case 9: divider = brahmslullaby[thisNote +1]; break;
}
if (divider > 0) noteDuration = (wholenote) / divider; // regular note, just proceed
else if (divider < 0) { // dotted notes are represented with negative durations
noteDuration = (wholenote) / abs(divider);
noteDuration *= 1.5; // increases the duration in half for dotted notes
}
noteIsOn = true;
elapsedNote = 0;
} //end of calculation of note duration
if (elapsedNote == 0) { //start to play note
switch (activeTune) {
case 0: ledcWriteTone(buzzChan,superMarioShort[thisNote]); break;
case 1: ledcWriteTone(buzzChan,darthVaderShort[thisNote]); break;
case 2: ledcWriteTone(buzzChan,pinkPantherShort[thisNote]); break;
case 3: ledcWriteTone(buzzChan,superMarioFull[thisNote]); break;
case 4: ledcWriteTone(buzzChan,darthVaderFull[thisNote]); break;
case 5: ledcWriteTone(buzzChan,pinkPantherFull[thisNote]); break;
case 6: ledcWriteTone(buzzChan,happybirthday[thisNote]); break;
case 7: ledcWriteTone(buzzChan,odetojoy[thisNote]); break;
case 8: ledcWriteTone(buzzChan,lionsleeps[thisNote]); break;
case 9: ledcWriteTone(buzzChan,brahmslullaby[thisNote]); break;
}
elapsedNote = millis();
}else{ // Wait for the specified duration before playing the next note
if (millis() - elapsedNote >= noteDuration) {
ledcWriteTone(buzzChan,0); // stop the waveform generation before the next note
noteIsOn = false;
thisNote += 2;
}
}
}else // tune has ended because thisNote > notes * 2
tuneIsOn = false;
}
void setup() //------------------------------------------------------------------SETUP
{
pinMode(buzzPin, OUTPUT);
ledcSetup(buzzChan, 10000, 12);
ledcAttachPin(buzzPin, buzzChan);
tuneIsOn = true; //flag to start or stop playback. To be used in program logic in loop()
activeTune = 4; //number of Tune to play. Can be defined by user input or as program logic
defineTunes();
}
void loop() //--------------------------------------------------------------------LOOP
{
if (tuneIsOn) chkOnTunes();
}
Amazing work! Kudos!
I made some changes to your code to make it non-blocking: instead of delay statements for each note and program logic waiting for the song to end, my changes allow for program execution while the tunes are being played.
Also I added a flag that can stop tune playback before it ends (for example if program logic requires it).
I also added the option to have up to 10 tunes selectable either by user input or by program logic.
Thanks!
Note: I don't know how to upload programs into a reported issue other than presenting the full code using markup language, so I renamed the NonBlockingTunes.INO and the tunes.h files to .TXT so that they could be copied here.
NonBlockingTunes.txt tunes.txt