Tagged “arduino”
-
Arduino music
Here is a nice code sample that I put together that plays music on the Arduino. Just hook up a speaker to pin 8, add a resistor if necessary, and it will play a few songs, one with multiple voices (polyphonic music).
` // Arduino Music Demo // James S. Ghofulpo // // Plays multi voice music. Documentation for writing your own music is below.
#define TS ( 130 ) // Time for a 1/16th note, in ms #define STACATTO ( 80 ) // Time for a stacatto note, in ms #define OUTPUT_PIN ( 8 ) // Which pin on the Arduino are we modulating #define NUM_VOICES ( 2 ) // Number of voices supported #define MAX_CYCLES ( 10 ) // On and off cycles before switch
// Data structure for each voice
typedef struct { float f; // Frequency long t; // Time left to play this note long decay_time; // Time left to decay (turn off) note long on_pt; // On phase time long off_pt; // Off phase time int synchronizing; // Set to 1 if we are waiting to synchronize int current_voice; // which voice is being analyzed in the muisc const char * music; const char * start_of_music; const char * return_pos; } voice_info_t;
// Function to play a song // // Tone Commands: // a-g - Select low octave note // A-G - Select high octave note // + - This note, up one octave // - - This note, down one octave // # - Sharp // & - Flat // t - Note is a triplet (1/3 of timing) // . - Note is dotted (timing * 1.5) // , - Note is stacatto // r - Rest // s, e, q, h, w - Timing (1/16, 1/8, 1/4, 1/2, 1) of note. Note plays when time is selected! // // Voice / flow commands: // // V - This is part of the next voice // >X - Call part X // [X yyyyy] - Define part x to be yyyyy // | - End of measure. Allows for synchronization, in case of misprogrammed music. // k - The previously mentioned note selects the key signature (i.e. fk selects F major).
void play_song( const char * this_song ) { int inx = 0; int iny; int duration = 0; int note_offset = -1; voice_info_t info[NUM_VOICES]; // Each voices' info int triplet = 0; int key[12]; long shortest_time = 999999; int current_phase = 0; long current_time; int in_combo; long time_in_micros; float on_duty_cycle = 0.1; int duty_cycle_direction = 0; int current_voice = 0; int cycle_count = 0; int dotted = 0; int stacatto = 0; char search_target; int everybody_is_done = 0; int accidental = 0;
for ( inx = 0; inx < NUM_VOICES; inx++ ) { info[inx].music = this_song; info[inx].start_of_music = this_song; info[inx].return_pos = this_song; info[inx].f = 0; info[inx].t = 0; info[inx].decay_time = 0; info[inx].on_pt = 0; // Frequency of this voice info[inx].off_pt = 0; info[inx].synchronizing = 0; info[inx].current_voice = 0; }
// Initialize key to C major
for ( inx = 0; inx < 12; inx++ ) { key[inx] = 0; }
//Serial.println( "Starting loop" );
while ( !everybody_is_done ) {
int everybody_is_synchronizing = 1; everybody_is_done = 1; // Assume we are all donefor ( inx = 0; inx < NUM_VOICES; inx++ ) { if ( *info[inx].music != 0 ) { everybody_is_done = 0;
if ( !info[inx].synchronizing ) // Somebody is still running... { everybody_is_synchronizing = 0; break; } }
}// If everybody is synchronizing, then we can continue.
if ( everybody_is_synchronizing ) { for ( inx = 0; inx < NUM_VOICES; inx++ ) { info[inx].synchronizing = 0; } }
// Code to check for the next note/sets of notes
for ( inx = 0; inx < NUM_VOICES; inx++ ) // Check all voices { while ( ( info[inx].t <= 0 ) // out of time, get next note && ( *info[inx].music != 0 ) // Still music left to play && ( !info[inx].synchronizing ) ) // And not waiting for everybody to be ready { // Serial.print( *info[inx].music );
switch( *info[inx].music ) { case '[': // Skip section [
music ]
while ( ( *info[inx].music != 0 ) && ( *info[inx].music != ']' ) ) { info[inx].music++; } break; case ']': info[inx].synchronizing = 1; // Wait for everybody to get done info[inx].music = info[inx].return_pos; info[inx].current_voice = 0; break; case 'V': // End of this part info[inx].current_voice++; break; // Do nothing: End marker case '>': // Call a subroutine info[inx].music++; // Get the marker search_target = *info[inx].music; info[inx].return_pos = info[inx].music; // The return position will be +1 info[inx].music = info[inx].start_of_music; // Rewind while ( ( *info[inx].music != '[' ) || ( *(info[inx].music+1) != search_target ) ) { info[inx].music++; } info[inx].music++; // Skip the bracket info[inx].music++; // Skip the marker
info[inx].current_voice = 0; // Starting with voice 0
info[inx].synchronizing = 1; // Wait for everybody to get done break; case '|': // Force synchronize between voices
if ( info[inx].current_voice == inx ) { info[inx].synchronizing = 1; // Wait for everybody to get done } break; case 'c': note_offset = 15; break; case 'd': note_offset = 17; break; case 'e': if ( note_offset == -1 ) note_offset = 19; else duration = TS * 2; // Eighth break; case 'f': note_offset = 20; break; case 'g': note_offset = 22; break; case 'a': note_offset = 24; break; case 'b': note_offset = 26; break; case 'C': note_offset = 27; break; case 'D': note_offset = 29; break; case 'E': note_offset = 31; break; case 'F': note_offset = 32; break; case 'G': note_offset = 34; break;
case 'A': note_offset = 36; break; case 'B': note_offset = 38; break;
case '+': note_offset += 12; break; // Up an octave case '-': note_offset -= 12; break; // Down an octave case '#': accidental = 1; break; // Up a half step case '&': accidental = -1; break; // Down a half step case 's': duration = TS; break; // Sixteenth case 'q': duration = TS * 4; break; // Quarter case 'h': duration = TS * 8; break; // Half case 'w': duration = TS * 16; break; // Whole case 'r': note_offset = -2; break; // Rest, not really necessary, except for eighth notes case 't': triplet = 1; break; // Duration is a triplet case '.': dotted = 1; break; // Dotted value case ',': stacatto = 1; break; // Stacatto // default: break; // Unhandled command }if ( *info[inx].music == 'k' ) // Handle keys { int base = note_offset % 12;
for ( iny = 0; iny < 12; iny++ ) { key[iny] = 0; }
int num_sharps = 0; int num_flats = 0;
switch ( base ) { case 0: key[3] = key[8] = key[10] = 1; break; // A case 1: key[2] = key[7] = -1; break; case 2: key[0] = key[3] = key[5] = key[8] = key[10] = 1; break; // B case 3: break; // C case 4: key[0] = key[2] = key[5] = key[7] = key[10] = -1; break; case 5: key[3] = key[8] = 1; break; // D case 6: key[0] = key[2] = key[7] = -1; break; case 7: key[3] = key[5] = key[8] = key[10] = 1; break; // E case 8: key[2] = -1; break; // F case 9: key[0] = key[2] = key[3] = key[5] = key[7] = key[10] = -1; break; case 10: key[8] = 1; break; // G case 11: key[0] = key[2] = key[5] = key[7] = -1; break;
}note_offset = -1; }
if ( duration != 0 ) // Note is complete { if ( triplet ) { duration /= 3; }
if ( dotted ) { duration = ((float)duration * 1.5); }
if ( info[inx].current_voice == inx ) // This note is for this voice {
info[inx].t = millis() + duration; info[inx].decay_time = info[inx].t - ( stacatto ? duration - STACATTO : 0 ); int base = note_offset % 12;// Sample code to add phasing effects to music /* if ( duty_cycle_direction == 0 ) { on_duty_cycle += 0.1;
if ( on_duty_cycle > 0.8 ) { duty_cycle_direction = 1; } } else { on_duty_cycle -= 0.1;
if ( on_duty_cycle < 0.2 ) { duty_cycle_direction = 0; } }
*/if ( note_offset >= 0 ) { info[inx].f = pow( 1.059460646483, note_offset + key[base] + accidental ) * 220.0; float pt = 1000000 / ( info[inx].f );
// The on phase time can be set here to add 'phasing' type effects /* on_pt[inx] = (long)( pt * on_duty_cycle );
if ( on_pt[inx] < 50 ) { on_pt[inx] = 50; }
on_pt[inx] = (long)( pt * on_duty_cycle ); */ info[inx].on_pt = 50;
info[inx].off_pt =(long)( pt - info[inx].on_pt ); } else // Rest { info[inx].f = 0; }
} // Else, this note is not for us// Reset parser note_offset = -1; duration = 0; triplet = 0; dotted = 0; stacatto = 0; accidental = 0; }
info[inx].music++; // Next character } } // Checked all voices
// Play the note / set of tones, until end of somebody's note
in_combo = 1;
while ( in_combo ) {
time_in_micros = micros();current_phase = !current_phase;
if ( info[current_voice].f == 0 ) // Rest all voices { digitalWrite( OUTPUT_PIN, LOW ); } else {
digitalWrite( OUTPUT_PIN, current_phase ? HIGH : LOW ); }if ( cycle_count++ > MAX_CYCLES ) // Check if we need to change voices { cycle_count = 0; current_time = millis(); int start_voice = current_voice;
do { current_voice = ( current_voice + 1 ) % NUM_VOICES; } while ( ( info[current_voice].f == 0 ) && ( current_voice != start_voice ) );
for ( inx = 0; inx < NUM_VOICES; inx++ ) { if ( current_time > info[inx].t ) // If this note has expired { info[inx].t = 0; // Request the next note info[inx].f = 0; // Turn off the note in_combo = 0; // Get next note
} else if ( current_time > info[inx].decay_time ) // stop this note { info[inx].f = 0; } } }if ( current_phase ) { shortest_time = info[current_voice].on_pt; } else { shortest_time = info[current_voice].off_pt; }
time_in_micros = micros() - time_in_micros;
delayMicroseconds( shortest_time - time_in_micros ); // Sleep the time minus time to process this loop
} } // While looping }// Here are some sample pieces of music. All songs, except for 'bourree', are single voice
// Super Mario Bros. char super_mario_bros[] = "[A EsEsrsEsrsCsEsrsG,ererq]" // Intro "[B C,ersg,ers,e,ersa,eb,ea#sasrs gtqEtqGtqA,eFsGsrsE,eCsDsbsre]" // Main music "[C reGsF#sFsD#srsEsrsg#sasCsrsasCsDs]" // Falling theme "[D reGsF#sFsD#srsEsrsC+srsC+sC+srsre]" // Falling end 1 "[E reD#sreDsreCersrerq]" // Falling end 2 "[F CsCsrsCsrsCsDsrsEsCsrsasgsrsre CsCsrsCsrsCsDsEsrh CsCsrsCsrsCsDsrsEsCsrsasgsrsre EsEsrsEsrsCsEsrsGsrsrerq]" // Finish "[G g-tqctqetqCtqEtqGqEq g-#tqctqe&tqg#gCtqE&tqG#qE&q a-#tqdtqftqa#tqDtqFtqA#qA#tqA#tqA#tq C+qqh]" // Finale "[H EsCsrsg,ersg#,easFsrsFsasrsre btqAtqAtqAtqGtqFtqEsCsrsasgsrsre EsCsrsg,ersg#,easFsrsFsasrsre bsFsrsFsFtqEtqDtqC,ererq]" ">A >B >B >C >D >C >E >F" // Play the intro and the main tune " >B >B >C >D >C >E >F" // Play the main tune again ">H >H >G"; // Play the second theme, followed by the finale
// char air[] = "ek eegefebegefses febegeCqbqa#e bi"; // Key of E
// Bourree by G.F. Handel, adapted from 'Music' by Software Technology Corp. char bourree[] = "[A" "gk Dq | D,qb,qCebea,eg,e | EqGhFeEe | DqC,e,beaebec,ea,e |" // M 1-4 " bqghaq | beC#ed,eb,eC#eDeE,eC#,e | DeEeF,eD,eE,eFeG,eE,e |" // M 5-7 " FeGeA+ereC#e | D.h" // M 8-9 "V bq | a,qg,qfeb-q | gqEqDqgere | fqrqgqfq |" // M1-4 " gqdhfq | gqaqgqeq | aqaqaqC#q | dhaqeq | f.h]" // m5-9 "[B" "gk A+q | AqFqGeFeEeDe | GqBhEq | D#qEqFqGeAe |" // M17-20 " GqEhDq | DqCebeCqCq | CqbeaebqDq | EeFeGeEeFeGeA+eFe |" // M21-24 " GeAeBeGeAeBeC+eAe | BqAeGeFeGeAeFe | GeAeBeAqCq | bqaegefegeaege |" // M25-28 " geaebegeaebeceae | beCeDqbqaege | g.h" // M29-31 "V Fq | FqDqDererq | dqb-ecedqeq | fqgqEqDq |" // M17-20 " bqEhDq | eqeheq | dqdhgq | ghah |" // M21-24 " DhDh | DqCebeaqDq | DqDqDqCq | dqrqrh |" // M25-28 " derereredererq | dererqdqcq | b-.h]" // M29-31 ">A >A >B >B"; // Play the two parts
char deck_the_halls[] = "[A g.qfeeqdq cqdqeqcq] " // Deck the halls with boughs of holly "[B deeefedee.qde cqb-qch] " // Fa la la la la la la la la "[C aeaeaeaeg.q fe eqdqch ]" // Last fa la la la ">A >B >A >B " "d.qeefqdq e.qfegqdq eefegqaebeCq bqaqgh " ">A >C";
char nyan_cat[] = "bk " // Key of B "[A D+sE+sF+eB+eD+sE+sF+sB+sC++sD++sC++sA+sB+e |" " F+ed+se+sF+eB+eC++sA+sB+sC++sE++sD++sE++sC++s]" // Intro music "[B FeGeDsDsrsbsD&sCsbsrsbeCe | D&eD&sCsbsCsDsFsGsdsfscsdsbscsbs " // Main theme " DeFeGsDsFsCsDsbsD&sDsD&sCsbscs | D&ebsCsDsFsCsDsCsbsCebece ]" "[C befsgsbefsgsbsCsDsbsesDsEsFs | bebefsgsbsfsEsDsCsbsfsdsesfs |" // Chorus " befsgsbefsgsbsbsCsDsbsfsgsfs ]" "[D bebsasbsfsgsbsEsDsEsFsbeae ]" // Chorus end 1 "[E bebsasbsfsgsbsEsDsEsFsbeCe ]" // Chorus end 2 "[F bebsasbsfsgsbsEsDsEsFsbe ]" // Chorus end 2, without last note ">A >B >B >C >D >C >E " " >B >B >C >D >C >F";
//char chord0[] = "cw"; //char chord1[] = "rwCwCwCwCwCwCw V cwdwewfwgwAwBwCwDwEwFwGw";
//char chord[] = "CwCwCw V gwgwgw V cedeeefegeAeBeCeDeEeFeGe"; char silence[] = "rwrwrw";void setup() { pinMode( OUTPUT_PIN, OUTPUT ); //Serial.begin( 115200 );
play_song( super_mario_bros ); play_song( silence );
play_song( nyan_cat ); play_song( silence );
play_song( deck_the_halls ); play_song( silence );
play_song( bourree ); play_song( silence ); }
void loop() { // no need to repeat the melody. } `
-
Arduino Bike Computer
I'm currently working on an Arduino based bike computer / data logger, based on a Arduino Uno and an SD shield. It seems to work quite well, and I use it for recording my progress on my bike trainer. I'm going to replace it with a RBBB and a micro-SD adapter I found online to make it portable.
See all tags.