change tone sounds by altering the waveforms

Dependencies:   mbed

Fork of 5_songs by MakingMusicWorkshop

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?

UserRevisionLine numberNew 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 }