Example of playing melodies using DAC.

Dependencies:   Joystick mbed

Fork of Melody by Craig Evans

Committer:
eencae
Date:
Tue Mar 01 15:58:55 2016 +0000
Revision:
0:f1e3ef53cc3c
Child:
1:7c149b76c057
Changed default melody.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eencae 0:f1e3ef53cc3c 1 /* Melody
eencae 0:f1e3ef53cc3c 2
eencae 0:f1e3ef53cc3c 3 Play a simple melody on the DAC using a look-up table for the sine waveform
eencae 0:f1e3ef53cc3c 4 Includes a primitive graphic equalizer on the LEDs
eencae 0:f1e3ef53cc3c 5
eencae 0:f1e3ef53cc3c 6 Craig A. Evans
eencae 0:f1e3ef53cc3c 7
eencae 0:f1e3ef53cc3c 8 March 2014
eencae 0:f1e3ef53cc3c 9
eencae 0:f1e3ef53cc3c 10 */
eencae 0:f1e3ef53cc3c 11
eencae 0:f1e3ef53cc3c 12 #include "mbed.h"
eencae 0:f1e3ef53cc3c 13 #include "tone.h" // note definitions
eencae 0:f1e3ef53cc3c 14
eencae 0:f1e3ef53cc3c 15 #define PI 3.14159265359
eencae 0:f1e3ef53cc3c 16
eencae 0:f1e3ef53cc3c 17 Timer noteTimer; // timer for note duration
eencae 0:f1e3ef53cc3c 18 AnalogOut aout(p18); // DAC on pin 18
eencae 0:f1e3ef53cc3c 19 BusOut leds(LED4,LED3,LED2,LED1); // LEDs for display
eencae 0:f1e3ef53cc3c 20
eencae 0:f1e3ef53cc3c 21 void initArray(); // function to initialise sample array
eencae 0:f1e3ef53cc3c 22 void tone(float frequency,float duration); // play a tone of set frequency for given duration
eencae 0:f1e3ef53cc3c 23 void graphicEqualizer(float frequency); // displays pattern on LEDs depending on the frequency
eencae 0:f1e3ef53cc3c 24
eencae 0:f1e3ef53cc3c 25 int n = 32; // number of samples
eencae 0:f1e3ef53cc3c 26 float y[32]; // array to store samples
eencae 0:f1e3ef53cc3c 27 float BPM = 73.0; // beats per minute
eencae 0:f1e3ef53cc3c 28
eencae 0:f1e3ef53cc3c 29 // comment one of the blocks out below - need noteArray[] and noteDuration[]
eencae 0:f1e3ef53cc3c 30
eencae 0:f1e3ef53cc3c 31 /*
eencae 0:f1e3ef53cc3c 32 // secret film melody...
eencae 0:f1e3ef53cc3c 33 float noteArray[] = {
eencae 0:f1e3ef53cc3c 34 NOTE_E4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_E4,NOTE_E4,NOTE_E4,
eencae 0:f1e3ef53cc3c 35 NOTE_E4,NOTE_G4,NOTE_G4,NOTE_G4,NOTE_G4,NOTE_E4,NOTE_E4,NOTE_E4,
eencae 0:f1e3ef53cc3c 36 NOTE_E4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_F4,NOTE_E4,NOTE_E4,NOTE_E4,
eencae 0:f1e3ef53cc3c 37 NOTE_E4,NOTE_G4,NOTE_G4,NOTE_G4,NOTE_G4,NOTE_E4,NOTE_E4,NOTE_E4,
eencae 0:f1e3ef53cc3c 38 NOTE_DS5,NOTE_D5,NOTE_B4,NOTE_A4,NOTE_B4,NOTE_E4,NOTE_G4,NOTE_DS5,
eencae 0:f1e3ef53cc3c 39 NOTE_D5,NOTE_G4,NOTE_B4,NOTE_B4,NOTE_FS5,NOTE_F5,NOTE_B4,NOTE_D5,
eencae 0:f1e3ef53cc3c 40 NOTE_AS5,NOTE_A5,NOTE_F5,NOTE_A5,NOTE_DS6,NOTE_D6
eencae 0:f1e3ef53cc3c 41 };
eencae 0:f1e3ef53cc3c 42
eencae 0:f1e3ef53cc3c 43 // durations of the notes
eencae 0:f1e3ef53cc3c 44 // 1/8th, 1/16th, 1/4th etc.
eencae 0:f1e3ef53cc3c 45 float noteDuration[] = {
eencae 0:f1e3ef53cc3c 46 8,16,16,8,4,8,8,8,
eencae 0:f1e3ef53cc3c 47 8,16,16,8,4,8,8,8,
eencae 0:f1e3ef53cc3c 48 8,16,16,8,4,8,8,8,
eencae 0:f1e3ef53cc3c 49 8,16,16,8,4,8,8,8,
eencae 0:f1e3ef53cc3c 50 8,2,8,8,1,8,4,8,
eencae 0:f1e3ef53cc3c 51 4,8,8,8,8,4,8,4,
eencae 0:f1e3ef53cc3c 52 8,4,8,4,8,3
eencae 0:f1e3ef53cc3c 53 };
eencae 0:f1e3ef53cc3c 54 */
eencae 0:f1e3ef53cc3c 55
eencae 0:f1e3ef53cc3c 56
eencae 0:f1e3ef53cc3c 57 // secret computer game melody...
eencae 0:f1e3ef53cc3c 58 float noteArray[] = {
eencae 0:f1e3ef53cc3c 59 NOTE_E7, NOTE_E7, 0, NOTE_E7,
eencae 0:f1e3ef53cc3c 60 0, NOTE_C7, NOTE_E7, 0,
eencae 0:f1e3ef53cc3c 61 NOTE_G7, 0, 0, 0,
eencae 0:f1e3ef53cc3c 62 NOTE_G6, 0, 0, 0,
eencae 0:f1e3ef53cc3c 63
eencae 0:f1e3ef53cc3c 64 NOTE_C7, 0, 0, NOTE_G6,
eencae 0:f1e3ef53cc3c 65 0, 0, NOTE_E6, 0,
eencae 0:f1e3ef53cc3c 66 0, NOTE_A6, 0, NOTE_B6,
eencae 0:f1e3ef53cc3c 67 0, NOTE_AS6, NOTE_A6, 0,
eencae 0:f1e3ef53cc3c 68
eencae 0:f1e3ef53cc3c 69 NOTE_G6, NOTE_E7, NOTE_G7,
eencae 0:f1e3ef53cc3c 70 NOTE_A7, 0, NOTE_F7, NOTE_G7,
eencae 0:f1e3ef53cc3c 71 0, NOTE_E7, 0,NOTE_C7,
eencae 0:f1e3ef53cc3c 72 NOTE_D7, NOTE_B6, 0, 0,
eencae 0:f1e3ef53cc3c 73
eencae 0:f1e3ef53cc3c 74 NOTE_C7, 0, 0, NOTE_G6,
eencae 0:f1e3ef53cc3c 75 0, 0, NOTE_E6, 0,
eencae 0:f1e3ef53cc3c 76 0, NOTE_A6, 0, NOTE_B6,
eencae 0:f1e3ef53cc3c 77 0, NOTE_AS6, NOTE_A6, 0,
eencae 0:f1e3ef53cc3c 78
eencae 0:f1e3ef53cc3c 79 NOTE_G6, NOTE_E7, NOTE_G7,
eencae 0:f1e3ef53cc3c 80 NOTE_A7, 0, NOTE_F7, NOTE_G7,
eencae 0:f1e3ef53cc3c 81 0, NOTE_E7, 0,NOTE_C7,
eencae 0:f1e3ef53cc3c 82 NOTE_D7, NOTE_B6, 0, 0
eencae 0:f1e3ef53cc3c 83 };
eencae 0:f1e3ef53cc3c 84
eencae 0:f1e3ef53cc3c 85 // durations of the notes
eencae 0:f1e3ef53cc3c 86 // 1/8th, 1/16th, 1/4th etc.
eencae 0:f1e3ef53cc3c 87 float noteDuration[] = {
eencae 0:f1e3ef53cc3c 88 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 89 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 90 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 91 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 92
eencae 0:f1e3ef53cc3c 93 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 94 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 95 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 96 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 97
eencae 0:f1e3ef53cc3c 98 9, 9, 9,
eencae 0:f1e3ef53cc3c 99 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 100 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 101 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 102
eencae 0:f1e3ef53cc3c 103 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 104 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 105 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 106 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 107
eencae 0:f1e3ef53cc3c 108 9, 9, 9,
eencae 0:f1e3ef53cc3c 109 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 110 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 111 12, 12, 12, 12,
eencae 0:f1e3ef53cc3c 112
eencae 0:f1e3ef53cc3c 113 };
eencae 0:f1e3ef53cc3c 114
eencae 0:f1e3ef53cc3c 115
eencae 0:f1e3ef53cc3c 116 int main()
eencae 0:f1e3ef53cc3c 117 {
eencae 0:f1e3ef53cc3c 118 initArray(); // fill array with sine samples
eencae 0:f1e3ef53cc3c 119
eencae 0:f1e3ef53cc3c 120 // calculate number of notes in array
eencae 0:f1e3ef53cc3c 121 //sizeof() returns number of BYTES in array,
eencae 0:f1e3ef53cc3c 122 // so divide by size of a float in BYTES to get number of elements
eencae 0:f1e3ef53cc3c 123 int notes = sizeof(noteArray)/sizeof(float);
eencae 0:f1e3ef53cc3c 124
eencae 0:f1e3ef53cc3c 125 while (1) {
eencae 0:f1e3ef53cc3c 126
eencae 0:f1e3ef53cc3c 127 // loop through notes
eencae 0:f1e3ef53cc3c 128 for(int i=0; i < notes; i++) {
eencae 0:f1e3ef53cc3c 129
eencae 0:f1e3ef53cc3c 130 // play note
eencae 0:f1e3ef53cc3c 131 tone(noteArray[i],60.0/(BPM*noteDuration[i]));
eencae 0:f1e3ef53cc3c 132 // leave a short pause between notes
eencae 0:f1e3ef53cc3c 133 wait(60.0/(BPM*noteDuration[i]));
eencae 0:f1e3ef53cc3c 134 }
eencae 0:f1e3ef53cc3c 135
eencae 0:f1e3ef53cc3c 136 wait(1.0); // wait a second before repeating
eencae 0:f1e3ef53cc3c 137
eencae 0:f1e3ef53cc3c 138 }
eencae 0:f1e3ef53cc3c 139
eencae 0:f1e3ef53cc3c 140 }
eencae 0:f1e3ef53cc3c 141
eencae 0:f1e3ef53cc3c 142 void initArray()
eencae 0:f1e3ef53cc3c 143 {
eencae 0:f1e3ef53cc3c 144 // create LUT - loop through array and calculate sine wave samples
eencae 0:f1e3ef53cc3c 145 for (int i = 0; i < n ; i++) {
eencae 0:f1e3ef53cc3c 146 y[i] = 0.5 + 0.5*sin(i*2*PI/n);
eencae 0:f1e3ef53cc3c 147 }
eencae 0:f1e3ef53cc3c 148
eencae 0:f1e3ef53cc3c 149 }
eencae 0:f1e3ef53cc3c 150
eencae 0:f1e3ef53cc3c 151 void tone(float frequency,float duration)
eencae 0:f1e3ef53cc3c 152 {
eencae 0:f1e3ef53cc3c 153 graphicEqualizer(frequency); // equalizer on LEDs
eencae 0:f1e3ef53cc3c 154
eencae 0:f1e3ef53cc3c 155 if (frequency > 0) { // a frequency of 0 indicates no note played so only play a note if frequency is not 0
eencae 0:f1e3ef53cc3c 156
eencae 0:f1e3ef53cc3c 157 float dt = 1.0/(frequency*n) - (1.34e-6 + 1e-6); // calculate time step - take into account DAC time and wait() offset
eencae 0:f1e3ef53cc3c 158
eencae 0:f1e3ef53cc3c 159 noteTimer.start(); // start timer
eencae 0:f1e3ef53cc3c 160
eencae 0:f1e3ef53cc3c 161 while(noteTimer.read() < duration) { // keep looping while timer less than duration
eencae 0:f1e3ef53cc3c 162
eencae 0:f1e3ef53cc3c 163 for (int i = 0; i < n ; i++) { // loop through samples and output analog waveform
eencae 0:f1e3ef53cc3c 164 aout = y[i];
eencae 0:f1e3ef53cc3c 165 wait(dt); // leave appropriate delay for frequency
eencae 0:f1e3ef53cc3c 166 }
eencae 0:f1e3ef53cc3c 167 }
eencae 0:f1e3ef53cc3c 168
eencae 0:f1e3ef53cc3c 169 noteTimer.stop(); // stop the timer
eencae 0:f1e3ef53cc3c 170 noteTimer.reset(); // reset to 0
eencae 0:f1e3ef53cc3c 171
eencae 0:f1e3ef53cc3c 172 } else { // if no note played, have a simple delay
eencae 0:f1e3ef53cc3c 173 wait(duration);
eencae 0:f1e3ef53cc3c 174 }
eencae 0:f1e3ef53cc3c 175
eencae 0:f1e3ef53cc3c 176 leds = 0; // turn off LEDs
eencae 0:f1e3ef53cc3c 177 }
eencae 0:f1e3ef53cc3c 178
eencae 0:f1e3ef53cc3c 179 // primitive graphic equalizer on the LEDs
eencae 0:f1e3ef53cc3c 180 void graphicEqualizer(float frequency)
eencae 0:f1e3ef53cc3c 181 {
eencae 0:f1e3ef53cc3c 182 // these numbers are fairly random and picked to give a
eencae 0:f1e3ef53cc3c 183 // decent effect when the melodies plays.
eencae 0:f1e3ef53cc3c 184 // Will have to change for different melodies
eencae 0:f1e3ef53cc3c 185 if (frequency < 123) {
eencae 0:f1e3ef53cc3c 186 leds = 0; // all off
eencae 0:f1e3ef53cc3c 187 }
eencae 0:f1e3ef53cc3c 188 else if (frequency < 440) {
eencae 0:f1e3ef53cc3c 189 leds = 8; // LED1
eencae 0:f1e3ef53cc3c 190 }
eencae 0:f1e3ef53cc3c 191 else if (frequency < 523) {
eencae 0:f1e3ef53cc3c 192 leds = 12; // LED1,LED2
eencae 0:f1e3ef53cc3c 193 }
eencae 0:f1e3ef53cc3c 194 else if (frequency < 1047) {
eencae 0:f1e3ef53cc3c 195 leds = 14; // LED1,LED2,LED3
eencae 0:f1e3ef53cc3c 196 }
eencae 0:f1e3ef53cc3c 197 else {
eencae 0:f1e3ef53cc3c 198 leds = 15; // LED1,LED2,LED3,LED4
eencae 0:f1e3ef53cc3c 199 }
eencae 0:f1e3ef53cc3c 200
eencae 0:f1e3ef53cc3c 201 }