Example of playing melodies using DAC.

Dependencies:   Joystick mbed

Fork of Melody by Craig Evans

main.cpp

Committer:
el16ecb
Date:
2017-03-02
Revision:
2:7804ced75c2f
Parent:
1:7c149b76c057

File content as of revision 2:7804ced75c2f:

/* Melody

Play a simple melody on the DAC using a look-up table for the sine waveform
Includes a primitive graphic equalizer on the LEDs

Craig A. Evans

March 2014

*/

#include "mbed.h"
#include "tone.h" // note definitions
#include <Joystick.h>

#define PI 3.14159265359

Timer noteTimer;  // timer for note duration
AnalogOut aout(p18);  // DAC on pin 18
BusOut leds(LED4,LED3,LED2,LED1);  // LEDs for display
Joystick stick = Joystick(p20,p19,p17);
PwmOut red_led (p24);
PwmOut green_led (p23);
PwmOut blue_led (p22);


void initArray();  // function to initialise sample array
void tone(float frequency,float duration);  // play a tone of set frequency for given duration
void graphicEqualizer(int frequency);  // displays pattern on LEDs depending on the frequency

int n = 32;  // number of samples
float y[32]; // array to store samples
float BPM = 73.0;  // beats per minute
Vector2D coord = stick.get_coord();
float xoffset = 1 - (coord.x/2);
float yoffset = 1 - (coord.y/5);

// comment one of the blocks out below - need noteArray[] and noteDuration[]

/*
// secret film melody...
float noteArray[] = {
    NOTE_E4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_E4,NOTE_E4,NOTE_E4,
    NOTE_E4,NOTE_G4,NOTE_G4,NOTE_G4,NOTE_G4,NOTE_E4,NOTE_E4,NOTE_E4,
    NOTE_E4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_E4,NOTE_E4,NOTE_E4,
    NOTE_E4,NOTE_G4,NOTE_G4,NOTE_G4,NOTE_G4,NOTE_E4,NOTE_E4,NOTE_E4,
    NOTE_DS5,NOTE_D5,NOTE_B4,NOTE_A4,NOTE_B4,NOTE_E4,NOTE_G4,NOTE_DS5,
    NOTE_D5,NOTE_G4,NOTE_B4,NOTE_B4,NOTE_FS5,NOTE_F5,NOTE_B4,NOTE_D5,
    NOTE_AS5,NOTE_A5,NOTE_F5,NOTE_A5,NOTE_DS6,NOTE_D6
};

// durations of the notes
// 1/8th, 1/16th, 1/4th etc.
float noteDuration[] = {
    8,16,16,8,4,8,8,8,
    8,16,16,8,4,8,8,8,
    8,16,16,8,4,8,8,8,
    8,16,16,8,4,8,8,8,
    8,2,8,8,1,8,4,8,
    4,8,8,8,8,4,8,4,
    8,4,8,4,8,3
};
*/


// secret computer game melody...
float noteArray[] = {
    //NOTE_E7, NOTE_E7, 0, NOTE_E7,
//    0, NOTE_C7, NOTE_E7, 0,
//    NOTE_G7, 0, 0,  0,
//    NOTE_G6, 0, 0, 0,
//
//    NOTE_C7, 0, 0, NOTE_G6,
//    0, 0, NOTE_E6, 0,
//    0, NOTE_A6, 0, NOTE_B6,
//    0, NOTE_AS6, NOTE_A6, 0,
//
//    NOTE_G6, NOTE_E7, NOTE_G7,
//    NOTE_A7, 0, NOTE_F7, NOTE_G7,
//    0, NOTE_E7, 0,NOTE_C7,
//    NOTE_D7, NOTE_B6, 0, 0,
//
//    NOTE_C7, 0, 0, NOTE_G6,
//    0, 0, NOTE_E6, 0,
//    0, NOTE_A6, 0, NOTE_B6,
//    0, NOTE_AS6, NOTE_A6, 0,
//
//    NOTE_G6, NOTE_E7, NOTE_G7,
//    NOTE_A7, 0, NOTE_F7, NOTE_G7,
//    0, NOTE_E7, 0,NOTE_C7,
//    NOTE_D7, NOTE_B6, 0, 0
    NOTE_G6, 0, NOTE_A7, 0,
    NOTE_E6, NOTE_E6, 0, NOTE_C6,

    NOTE_DS6, NOTE_D6, NOTE_C6, 0,
    NOTE_C6, 0, NOTE_D6, 0,

    NOTE_DS6, 0, NOTE_DS6, NOTE_D6,
    NOTE_C6, NOTE_D6, NOTE_E6, NOTE_G6,

    NOTE_A7, NOTE_E6, NOTE_G7, NOTE_D6,
    NOTE_E6, NOTE_C6, NOTE_D6, NOTE_C6,

    NOTE_E6, 0, NOTE_G6, 0,
    NOTE_A7, NOTE_E6, NOTE_G6, NOTE_D6,

    NOTE_E6, NOTE_C6, NOTE_DS6, NOTE_E6,
    NOTE_DS6, NOTE_D6, NOTE_C6, NOTE_D6,

    NOTE_DS6, 0, NOTE_C6, NOTE_D6,
    NOTE_E6, NOTE_G6, NOTE_D6, NOTE_E6,

    NOTE_D6, NOTE_C6, NOTE_D6, 0,
    NOTE_C6, 0, NOTE_D6, 0,

    NOTE_G6, 0, NOTE_A7, 0,
    NOTE_E6, NOTE_E6, 0, NOTE_C6,

    NOTE_DS6, NOTE_D6, NOTE_C6, 0,
    NOTE_C6, 0, NOTE_D6, 0,

    NOTE_DS6, 0, NOTE_DS6, NOTE_D6,
    NOTE_C6, NOTE_D6, NOTE_E6, NOTE_G6,

    NOTE_A7, NOTE_E6, NOTE_G7, NOTE_D6,
    NOTE_E6, NOTE_C6, NOTE_D6, NOTE_C6,

    NOTE_E6, 0, NOTE_G6, 0,
    NOTE_A7, NOTE_E6, NOTE_G6, NOTE_D6,

    NOTE_E6, NOTE_C6, NOTE_DS6, NOTE_E6,
    NOTE_DS6, NOTE_D6, NOTE_C6, NOTE_D6,

    NOTE_DS6, 0, NOTE_C6, NOTE_D6,
    NOTE_E6, NOTE_G6, NOTE_D6, NOTE_E6,

    NOTE_D6, NOTE_C6, NOTE_D6, 0,
    NOTE_C6, 0, NOTE_C6, 0,

    NOTE_C6, 0, NOTE_G5, NOTE_A6,
    NOTE_C6, 0, NOTE_G5, NOTE_A6,

    NOTE_C6, NOTE_D6, NOTE_E6, NOTE_C6,
    NOTE_F6, NOTE_E6, NOTE_F6, NOTE_G6,

    NOTE_C6, 0, NOTE_C6, 0,
    NOTE_G5, NOTE_A6, NOTE_C6, NOTE_G6,

    NOTE_F6, NOTE_E6, NOTE_D6, NOTE_C6,
    NOTE_F5, NOTE_E5, NOTE_F5, NOTE_G5,

    NOTE_C6, 0, NOTE_G5, NOTE_A6,
    NOTE_C6, 0, NOTE_G5, NOTE_A6,

    NOTE_C6, NOTE_C6, NOTE_D6, NOTE_E6,
    NOTE_C6, NOTE_G5, NOTE_A6, NOTE_G5,

    NOTE_C6, 0, NOTE_C6, NOTE_B6,
    NOTE_C5, NOTE_G5, NOTE_A6, NOTE_C6,

    NOTE_F6, NOTE_E6, NOTE_F6, NOTE_G6,
    NOTE_C6, 0, NOTE_B6, 0,

    NOTE_C6, 0, NOTE_G5, NOTE_A6,
    NOTE_C6, 0, NOTE_G5, NOTE_A6,

    NOTE_C6, NOTE_D6, NOTE_E6, NOTE_C6,
    NOTE_F6, NOTE_E6, NOTE_F6, NOTE_G6,

    NOTE_C6, 0, NOTE_C6, 0,
    NOTE_G5, NOTE_A6, NOTE_C6, NOTE_G6,

    NOTE_F6, NOTE_E6, NOTE_D6, NOTE_C6,
    NOTE_F5, NOTE_E5, NOTE_F5, NOTE_G5,

    NOTE_C6, 0, NOTE_G5, NOTE_A6,
    NOTE_C6, 0, NOTE_G5, NOTE_A6,

    NOTE_C6, NOTE_C6, NOTE_D6, NOTE_E6,
    NOTE_C6, NOTE_G5, NOTE_A6, NOTE_G5,

    NOTE_C6, 0, NOTE_C6, NOTE_B6,
    NOTE_C5, NOTE_G5, NOTE_A6, NOTE_C6,

    NOTE_F6, NOTE_E6, NOTE_F6, NOTE_G6,
    NOTE_C6, 0, NOTE_D6, 0,
};

// durations of the notes
// 1/8th, 1/16th, 1/4th etc.
float noteDuration[] = {
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,
    18, 18, 18, 18,

};


int main()
{
    initArray(); // fill array with sine samples

    // calculate number of notes in array
    //sizeof() returns number of BYTES in array,
    // so divide by size of a float in BYTES to get number of elements
    int notes = sizeof(noteArray)/sizeof(float);

    while (1) {

        // loop through notes
        for(int i=0; i < notes; i++) {
            Vector2D coord = stick.get_coord();
            int modi = (yoffset + coord.y/5)*noteArray[i];
            float modt = (xoffset + coord.x/2)*noteDuration[i];
            printf("%d %d \n",modi,i);
            // play note
            tone(modi,60.0/(BPM*modt));
            // leave a short pause between notes
            wait(60.0/(BPM*modt));
        }

        wait(1.0);  // wait a second before repeating

    }

}

void initArray()
{
    // create LUT - loop through array and calculate sine wave samples
    for (int i = 0; i < n ; i++) {
        y[i] = 0.5 + 0.5*sin(i*2*PI/n);
    }

}

void tone(float frequency,float duration)
{
    int newfreq = int(frequency);
    graphicEqualizer(newfreq);  // equalizer on LEDs

    if (frequency > 0) {  // a frequency of 0 indicates no note played so only play a note if frequency is not 0

        float dt = 1.0/(frequency*n) - (1.34e-6 + 1e-6);  // calculate time step - take into account DAC time and wait() offset

        noteTimer.start(); // start timer

        while(noteTimer.read() < duration) { // keep looping while timer less than duration

            for (int i = 0; i < n ; i++) {  // loop through samples and output analog waveform
                aout = y[i];
                wait(dt); // leave appropriate delay for frequency
            }
        }

        noteTimer.stop();  // stop the timer
        noteTimer.reset(); // reset to 0

    } else { // if no note played, have a simple delay
        wait(duration);
    }

    leds = 0;   // turn off LEDs
}

// primitive graphic equalizer on the LEDs
void graphicEqualizer(int frequency)
{
    // these numbers are fairly random and picked to give a
    // decent effect when the melodies plays.
    // Will have to change for different melodies
    //printf("%f",float((frequency%63)/63.0));
    red_led = ((frequency%31)/31.0);
    green_led = (((frequency)%37)/37.0);
    blue_led = (((frequency)%41)/41.0);

}