change tone sounds by altering the waveforms
Dependencies: mbed
Fork of 5_songs by
main.cpp@9:bf01a27b649f, 2016-05-21 (annotated)
- Committer:
- maclobdell
- Date:
- Sat May 21 17:20:54 2016 +0000
- Revision:
- 9:bf01a27b649f
- Parent:
- 8:77227ecac915
clean up.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
maclobdell | 0:0fb17f0d39e7 | 1 | #include "mbed.h" // this tells us to load mbed related functions |
maclobdell | 1:8922cc02aec7 | 2 | #include "tones.h" // list of all the tones and their frequencies |
maclobdell | 0:0fb17f0d39e7 | 3 | |
maclobdell | 0:0fb17f0d39e7 | 4 | PwmOut buzzer(D3); // our buzzer is a PWM output (pulse-width modulation) |
maclobdell | 0:0fb17f0d39e7 | 5 | |
maclobdell | 5:7003c9f6d633 | 6 | static int BPM = 80; |
maclobdell | 0:0fb17f0d39e7 | 7 | |
maclobdell | 0:0fb17f0d39e7 | 8 | static void silence() { |
maclobdell | 0:0fb17f0d39e7 | 9 | buzzer.write(0.0f); // silence! |
maclobdell | 0:0fb17f0d39e7 | 10 | } |
maclobdell | 0:0fb17f0d39e7 | 11 | |
maclobdell | 0:0fb17f0d39e7 | 12 | // this is our function that plays a tone. |
maclobdell | 0:0fb17f0d39e7 | 13 | // Takes in a tone frequency, and after duration (in ms.) we stop playing again |
maclobdell | 7:4730853634bf | 14 | static void play_tone(int tone, int duration) { |
maclobdell | 7:4730853634bf | 15 | |
maclobdell | 7:4730853634bf | 16 | int tone_period_us = 1000000/tone; |
maclobdell | 9:bf01a27b649f | 17 | |
maclobdell | 7:4730853634bf | 18 | for (long i = 0; i < duration * 1000L; i += tone_period_us * 2) { |
maclobdell | 7:4730853634bf | 19 | |
maclobdell | 7:4730853634bf | 20 | // let's change the buzzer's volume depending on how far we are |
maclobdell | 7:4730853634bf | 21 | float pct = (float)i / (float)(duration * 1000L); |
maclobdell | 7:4730853634bf | 22 | |
maclobdell | 7:4730853634bf | 23 | buzzer = (1 - pct) / 4; // high to low |
maclobdell | 7:4730853634bf | 24 | wait_us(tone_period_us); |
maclobdell | 7:4730853634bf | 25 | buzzer = 0.0f; |
maclobdell | 7:4730853634bf | 26 | wait_us(tone_period_us); |
maclobdell | 7:4730853634bf | 27 | } |
maclobdell | 9:bf01a27b649f | 28 | /* |
maclobdell | 8:77227ecac915 | 29 | #define PI 3.14159265 |
maclobdell | 8:77227ecac915 | 30 | |
maclobdell | 8:77227ecac915 | 31 | for (long i = 0; i < duration * 1000L; i += tone_period_us * 2) { |
maclobdell | 8:77227ecac915 | 32 | // let's change the buzzer's volume depending on how far we are |
maclobdell | 8:77227ecac915 | 33 | float pct = (float)i / (float)(duration * 1000L); |
maclobdell | 8:77227ecac915 | 34 | |
maclobdell | 8:77227ecac915 | 35 | // make 4 sinus forms (8 * PI), then map it from -1..1 to 0.1..0.6, |
maclobdell | 8:77227ecac915 | 36 | // then divide by 8 to not make too much sound |
maclobdell | 8:77227ecac915 | 37 | buzzer = (sin(pct * (8 * PI)) / 2 + 0.6) / 8; |
maclobdell | 8:77227ecac915 | 38 | wait_us(tone_period_us); |
maclobdell | 8:77227ecac915 | 39 | buzzer = 0.0f; |
maclobdell | 8:77227ecac915 | 40 | wait_us(tone_period_us); |
maclobdell | 8:77227ecac915 | 41 | } |
maclobdell | 8:77227ecac915 | 42 | |
maclobdell | 8:77227ecac915 | 43 | buzzer = 0.0f; |
maclobdell | 9:bf01a27b649f | 44 | */ |
maclobdell | 0:0fb17f0d39e7 | 45 | } |
maclobdell | 0:0fb17f0d39e7 | 46 | |
maclobdell | 0:0fb17f0d39e7 | 47 | static void play_song(int notes_left, int* melody, int* duration) { |
maclobdell | 1:8922cc02aec7 | 48 | |
maclobdell | 7:4730853634bf | 49 | // melody and duration are pointers, they point to the array of tones and durations we declared earlier |
maclobdell | 7:4730853634bf | 50 | // every time we play a note we up these pointers (move one element forward) |
maclobdell | 7:4730853634bf | 51 | // so the current tone is always the first element of melody (same for duration) |
maclobdell | 7:4730853634bf | 52 | |
maclobdell | 7:4730853634bf | 53 | int length; |
maclobdell | 7:4730853634bf | 54 | |
maclobdell | 7:4730853634bf | 55 | while(notes_left > 0) |
maclobdell | 7:4730853634bf | 56 | { |
maclobdell | 7:4730853634bf | 57 | |
maclobdell | 7:4730853634bf | 58 | int tone = melody[0]; |
maclobdell | 7:4730853634bf | 59 | // BPM is quarter notes per minute, so length in milliseconds is: |
maclobdell | 7:4730853634bf | 60 | length = static_cast<int>(static_cast<float>(1000 / duration[0]) * (60000.0f / static_cast<float>(BPM * 1000))); |
maclobdell | 7:4730853634bf | 61 | |
maclobdell | 7:4730853634bf | 62 | play_tone(tone, length); |
maclobdell | 7:4730853634bf | 63 | |
maclobdell | 7:4730853634bf | 64 | // after the full length of this tone, we up the melody, and down the notes_left |
maclobdell | 7:4730853634bf | 65 | |
maclobdell | 7:4730853634bf | 66 | notes_left--; |
maclobdell | 7:4730853634bf | 67 | melody++; |
maclobdell | 7:4730853634bf | 68 | duration++; |
maclobdell | 7:4730853634bf | 69 | |
maclobdell | 7:4730853634bf | 70 | } |
maclobdell | 7:4730853634bf | 71 | |
maclobdell | 7:4730853634bf | 72 | // we're done! just finish this note and silence |
maclobdell | 7:4730853634bf | 73 | wait_ms(length / 2); |
maclobdell | 7:4730853634bf | 74 | silence(); |
maclobdell | 2:610196c7b41c | 75 | |
maclobdell | 0:0fb17f0d39e7 | 76 | } |
maclobdell | 0:0fb17f0d39e7 | 77 | |
maclobdell | 0:0fb17f0d39e7 | 78 | // this code runs when the microcontroller starts up |
maclobdell | 1:8922cc02aec7 | 79 | int main() { |
maclobdell | 2:610196c7b41c | 80 | |
maclobdell | 0:0fb17f0d39e7 | 81 | // declare a melody |
maclobdell | 6:406f73a0eb49 | 82 | int melody[] = { |
maclobdell | 6:406f73a0eb49 | 83 | NOTE_C4, NOTE_D4, NOTE_DS4, NOTE_C4, NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4, |
maclobdell | 6:406f73a0eb49 | 84 | NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4, |
maclobdell | 6:406f73a0eb49 | 85 | NOTE_FS4, NOTE_G4, NOTE_FS4, NOTE_G4 |
maclobdell | 0:0fb17f0d39e7 | 86 | }; |
maclobdell | 2:610196c7b41c | 87 | |
maclobdell | 0:0fb17f0d39e7 | 88 | // note durations: 4 = quarter note, 8 = eighth note, etc.: |
maclobdell | 6:406f73a0eb49 | 89 | // the rapid succession of 16th notes produces a twill effect |
maclobdell | 0:0fb17f0d39e7 | 90 | int duration[] = { |
maclobdell | 6:406f73a0eb49 | 91 | 2, 8, 4, 4, 16, 16, 16, 16, |
maclobdell | 6:406f73a0eb49 | 92 | 16, 16, 16, 16, 16, 16, 16, |
maclobdell | 6:406f73a0eb49 | 93 | 16, 16, 16, 16, 16 |
maclobdell | 2:610196c7b41c | 94 | }; |
maclobdell | 7:4730853634bf | 95 | |
maclobdell | 0:0fb17f0d39e7 | 96 | // melody & duration are on the heap, need to get them on the stack |
maclobdell | 0:0fb17f0d39e7 | 97 | int *m = new int[sizeof(melody) / sizeof(int)]; |
maclobdell | 0:0fb17f0d39e7 | 98 | memcpy(m, melody, sizeof(melody)); |
maclobdell | 0:0fb17f0d39e7 | 99 | int *d = new int[sizeof(duration) / sizeof(int)]; |
maclobdell | 0:0fb17f0d39e7 | 100 | memcpy(d, duration, sizeof(duration)); |
maclobdell | 0:0fb17f0d39e7 | 101 | |
maclobdell | 0:0fb17f0d39e7 | 102 | if (sizeof(melody) != sizeof(duration)) { |
maclobdell | 0:0fb17f0d39e7 | 103 | printf("Melody and duration do not have same number of elements! Aborting!\r\n"); |
maclobdell | 2:610196c7b41c | 104 | return 1; |
maclobdell | 0:0fb17f0d39e7 | 105 | } |
maclobdell | 0:0fb17f0d39e7 | 106 | |
maclobdell | 0:0fb17f0d39e7 | 107 | play_song(sizeof(melody) / sizeof(int), m, d); |
maclobdell | 2:610196c7b41c | 108 | |
maclobdell | 2:610196c7b41c | 109 | return 0; |
maclobdell | 0:0fb17f0d39e7 | 110 | } |