change tone sounds by altering the waveforms

Dependencies:   mbed

Fork of 5_songs by MakingMusicWorkshop

main.cpp

Committer:
maclobdell
Date:
2016-05-21
Revision:
9:bf01a27b649f
Parent:
8:77227ecac915

File content as of revision 9:bf01a27b649f:

#include "mbed.h"       // this tells us to load mbed  related functions
#include "tones.h"      // list of all the tones and their frequencies

PwmOut buzzer(D3);                   // our buzzer is a PWM output (pulse-width modulation)

static int BPM = 80;

static void silence() {
    buzzer.write(0.0f); // silence!
}

// this is our function that plays a tone. 
// Takes in a tone frequency, and after duration (in ms.) we stop playing again
static void play_tone(int tone, int duration) {

   int tone_period_us = 1000000/tone;
    
   for (long i = 0; i < duration * 1000L; i += tone_period_us * 2) {

        // let's change the buzzer's volume depending on how far we are
        float pct = (float)i / (float)(duration * 1000L);

        buzzer = (1 - pct) / 4; // high to low
        wait_us(tone_period_us);
        buzzer = 0.0f;
        wait_us(tone_period_us);
    }
/*
#define PI 3.14159265

    for (long i = 0; i < duration * 1000L; i += tone_period_us * 2) {
        // let's change the buzzer's volume depending on how far we are
        float pct = (float)i / (float)(duration * 1000L);

        // make 4 sinus forms (8 * PI), then map it from -1..1 to 0.1..0.6,
        // then divide by 8 to not make too much sound
        buzzer = (sin(pct * (8 * PI)) / 2 + 0.6) / 8;
        wait_us(tone_period_us);
        buzzer = 0.0f;
        wait_us(tone_period_us);
    }

    buzzer = 0.0f;
*/
}

static void play_song(int notes_left, int* melody, int* duration) {
    
   // melody and duration are pointers, they point to the array of tones and durations we declared earlier
    // every time we play a note we up these pointers (move one element forward)
    // so the current tone is always the first element of melody (same for duration)
 
    int length;
 
    while(notes_left > 0)
    {
 
        int tone = melody[0];
        // BPM is quarter notes per minute, so length in milliseconds is:
        length = static_cast<int>(static_cast<float>(1000 / duration[0]) * (60000.0f / static_cast<float>(BPM * 1000)));
 
        play_tone(tone, length);
                    
        // after the full length of this tone, we up the melody, and down the notes_left
        
        notes_left--;
        melody++;
        duration++;
            
    }  
 
    // we're done! just finish this note and silence
    wait_ms(length / 2);  
    silence();  

}

// this code runs when the microcontroller starts up
int main() {

    // declare a melody
     int melody[] = {
        NOTE_C4, NOTE_D4, NOTE_DS4, NOTE_C4, NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4, 
        NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4, 
        NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4    
    };
 
    // note durations: 4 = quarter note, 8 = eighth note, etc.:
    // the rapid succession of 16th notes produces a twill effect
    int duration[] = {
        2, 8, 4, 4, 16, 16, 16, 16, 
        16, 16, 16, 16, 16, 16, 16, 
        16, 16, 16, 16, 16 
    };    
     
    // melody & duration are on the heap, need to get them on the stack
    int *m = new int[sizeof(melody) / sizeof(int)];
    memcpy(m, melody, sizeof(melody));
    int *d = new int[sizeof(duration) / sizeof(int)];
    memcpy(d, duration, sizeof(duration));
    
    if (sizeof(melody) != sizeof(duration)) {
        printf("Melody and duration do not have same number of elements! Aborting!\r\n");
        return 1;
    }
    
    play_song(sizeof(melody) / sizeof(int), m, d);
    
    return 0;
}