Edward Baker
/
Melody
Example of playing melodies using DAC.
Fork of Melody by
main.cpp@0:f1e3ef53cc3c, 2016-03-01 (annotated)
- 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?
User | Revision | Line number | New 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 | } |