Skip to content

Instantly share code, notes, and snippets.

@dmiddlecamp
Created October 22, 2016 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmiddlecamp/5a93cf5b66404876b7e5d4bfa8783014 to your computer and use it in GitHub Desktop.
Save dmiddlecamp/5a93cf5b66404876b7e5d4bfa8783014 to your computer and use it in GitHub Desktop.
#include "math.h"
const char nyan_cat_intro[] = "DS5,16,E5,16,FS5,8,B5,8,DS5,16,E5,16,FS5,16,B5,16,CS6,16,DS6,16,CS6,16,AS5,16,B5,8,FS5,8,DS5,16,E5,16,FS5,8,B5,8,CS6,16,AS5,16,B5,16,CS6,16,E6,16,DS6,16,E6,16,B5,16\n";
const char nyan_cat_melody[] = "FS5,8,GS5,8,DS5,16,DS5,16,R,16,B4,16,D5,16,CS5,16,B4,16,R,16,B4,8,CS5,8,D5,8,D5,16,CS5,16,B4,16,CS5,16,DS5,16,FS5,16,GS5,16,DS5,16,FS5,16,CS5,16,DS5,16,B4,16,CS5,16,B4,16,DS5,8,FS5,8,GS5,16,DS5,16,FS5,16,CS5,16,DS5,16,B4,16,D5,16,DS5,16,D5,16,CS5,16,B4,16,CS5,16,D5,8,B4,16,CS5,16,DS5,16,FS5,16,CS5,16,DS5,16,CS5,16,B4,16,CS5,8,B4,8,CS5,8,FS5,8,GS5,8,DS5,16,DS5,16,R,16,B4,16,D5,16,CS5,16,B4,16,R,16,B4,8,CS5,8,D5,8,D5,16,CS5,16,B4,16,CS5,16,DS5,16,FS5,16,GS5,16,DS5,16,FS5,16,CS5,16,DS5,16,B4,16,CS5,16,B4,16,DS5,8,FS5,8,GS5,16,DS5,16,FS5,16,CS5,16,DS5,16,B4,16,D5,16,DS5,16,D5,16,CS5,16,B4,16,CS5,16,D5,8,B4,16,CS5,16,DS5,16,FS5,16,CS5,16,DS5,16,CS5,16,B4,16,CS5,8,B4,8,CS5,8,B4,8,FS4,16,GS4,16,B4,8,FS4,16,GS4,16,B4,16,CS5,16,DS5,16,B4,16,E5,16,DS5,16,E5,16,FS5,16,B4,8,B4,8,FS4,16,GS4,16,B4,16,FS4,16,E5,16,DS5,16,CS5,16,B4,16,FS4,16,DS4,16,E4,16,FS4,16,B4,8,FS4,16,GS4,16,B4,8,FS4,16,GS4,16,B4,16,B4,16,CS5,16,DS5,16,B4,16,FS4,16,GS4,16,FS4,16,B4,8,B4,16,AS4,16,B4,16,FS4,16,GS4,16,E4,16,E5,16,DS5,16,E5,16,FS5,16,B4,8,AS4,8,B4,8,FS4,16,GS4,16,B4,8,FS4,16,GS4,16,B4,16,CS5,16,DS5,16,B4,16,E5,16,DS5,16,E5,16,FS5,16,B4,8,B4,8,FS4,16,GS4,16,B4,16,FS4,16,E5,16,DS5,16,CS5,16,B4,16,FS4,16,DS4,16,E4,16,FS4,16,B4,8,FS4,16,GS4,16,B4,8,FS4,16,GS4,16,B4,16,B4,16,CS5,16,DS5,16,B4,16,FS4,16,GS4,16,FS4,16,B4,8,B4,16,AS4,16,B4,16,FS4,16,GS4,16,B4,16,E5,16,DS5,16,E5,16,FS5,16,B4,8,CS5,8\n";
String nyan_song = String(nyan_cat_melody);
char inputStr[2048];
char* note;
char* duration;
int bpm = 110;
void setup() {
pinMode(D0, OUTPUT);
nyan_song.toCharArray(inputStr, nyan_song.length());
note = strtok(inputStr,",");
duration = strtok(NULL,", \n");
}
void loop() {
//tone(D0, 220, 500);
playNote(note, atoi(duration));
if (duration != NULL) {
// advance the note
note = strtok(NULL,",");
duration = strtok(NULL,", \n");
}
else {
nyan_song.toCharArray(inputStr, nyan_song.length());
note = strtok(inputStr,",");
duration = strtok(NULL,", \n");
}
// delay(1000);
}
void playNote(String note, int duration) {
int noteNum = 0;
int noteSharp = 0;
int noteFlat = 0;
int octave = 5;
int freq = 256;
int octIndex = note.length()-1; // octave is the last char
String tempOctave = note.substring(octIndex, octIndex+1);
octave = tempOctave.toInt();
String tempNote = note.substring(0, octIndex);
tempNote.toUpperCase();
if (tempNote.length()==2) {
if (tempNote.charAt(1)=='S' || tempNote.charAt(1)=='#') {
noteSharp = 1;
} else if (tempNote.charAt(1)=='B') {
noteFlat = 1;
}
}
// Using 240 instead of 250 after calibrating at 60 BPM and 240 BPM with a stopwatch.
// Seems to work well with and without Serial logging, so that is ok to leave uncommented below.
if (duration != 0) {
duration = 1000*240/bpm/duration;
}
switch (tempNote.charAt(0)) {
case 'C':
noteNum = 0 + noteSharp;
break;
case 'D':
noteNum = 2 + noteSharp - noteFlat;
break;
case 'E':
noteNum = 4 - noteFlat;
break;
case 'F':
noteNum = 5 + noteSharp;
break;
case 'G':
noteNum = 7 + noteSharp - noteFlat;
break;
case 'A':
noteNum = 9 + noteSharp - noteFlat;
break;
case 'B':
noteNum = 11 - noteFlat;
break;
case 'R': // Rest note 'R' or 'REST'
octave = -1;
break;
default:
break;
}
// based on equation at http://www.phy.mtu.edu/~suits/NoteFreqCalcs.html and the Verdi tuning
// fn = f0*(2^1/12)^n where n = number of half-steps from the reference frequency f0
freq = float(256*pow(1.05946,( 12.0*(octave-4) +noteNum)));
// C4^ (2^1/12)^ 12 half-steps in an octave ^how many extra half-steps within that octave, 0 for 'C'
// Serial.printlnf("%-3s o:%-2d f:%-5d d:%d", tempNote.c_str(), octave, int(freq), duration);
if (octave != -1) tone(D0, int(freq), duration);
delay(duration);
if (octave != -1) noTone(D0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment