mirror of
https://github.com/taigrr/arduinolibs
synced 2025-01-18 04:33:12 -08:00
Melody class for playing simple tunes using tone()
This commit is contained in:
parent
f9e77a9cf3
commit
8c676d8e71
@ -610,7 +610,7 @@ WARN_LOGFILE =
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = ../libraries/FreetronicsLCD ../libraries/BlinkLED ../libraries/BitBangI2C .
|
||||
INPUT = ../libraries/FreetronicsLCD ../libraries/BlinkLED ../libraries/BitBangI2C ../libraries/Melody .
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
|
219
libraries/Melody/Melody.cpp
Normal file
219
libraries/Melody/Melody.cpp
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Southern Storm Software, Pty Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Melody.h"
|
||||
#include <WProgram.h>
|
||||
|
||||
/**
|
||||
* \class Melody Melody.h <Melody.h>
|
||||
* \brief Plays a melody on a digital output pin using tone().
|
||||
*
|
||||
* The following example plays a simple tone three times on digital pin 8:
|
||||
*
|
||||
* \code
|
||||
* #include <Melody.h>
|
||||
*
|
||||
* int notes[] = {
|
||||
* NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3,
|
||||
* NOTE_REST, NOTE_B3, NOTE_C4, NOTE_REST
|
||||
* };
|
||||
* byte lengths[] = {4, 8, 8, 4, 4, 4, 4, 4, 2};
|
||||
*
|
||||
* Melody melody(8);
|
||||
*
|
||||
* void setup() {
|
||||
* melody.setMelody(notes, lengths, sizeof(lengths));
|
||||
* melody.setLoopCount(3);
|
||||
* melody.play();
|
||||
* }
|
||||
*
|
||||
* void loop() {
|
||||
* melody.run();
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* The \c notes array contains the frequency of the notes to be played,
|
||||
* with the special value \c NOTE_REST indicating a rest where no notes
|
||||
* are playing. The \c lengths array contains the lengths of each of the
|
||||
* notes; a value of 4 indicates a quarter note, a value of 8 indicates
|
||||
* an eighth note, etc.
|
||||
*
|
||||
* The run() method must be called from the application's main
|
||||
* <tt>loop()</tt> method to ensure that the melody advances from
|
||||
* one note to the next. It will not * block the application while
|
||||
* notes are playing.
|
||||
*
|
||||
* The number of loops can also be specified with setLoopDuration() which
|
||||
* sets a maximum amount of time that the melody will play before stopping.
|
||||
* The following example plays the melody for no more than 60 seconds:
|
||||
*
|
||||
* \code
|
||||
* void setup() {
|
||||
* melody.setMelody(notes, lengths, sizeof(lengths));
|
||||
* melody.setLoopDuration(60000UL);
|
||||
* melody.play();
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Constructs a new melody playing object for \a pin.
|
||||
*/
|
||||
Melody::Melody(uint8_t pin)
|
||||
: _pin(pin)
|
||||
, playing(false)
|
||||
, _loopCount(0)
|
||||
, loopsLeft(0)
|
||||
, notes(0)
|
||||
, lengths(0)
|
||||
, size(0)
|
||||
, posn(0)
|
||||
, duration(0)
|
||||
, startNote(0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* \fn bool Melody::isPlaying() const
|
||||
* \brief Returns true if the melody is currently playing; false if not.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn int Melody::loopCount() const
|
||||
* \brief Returns the number of times the melody should loop before stopping.
|
||||
*
|
||||
* The default value is zero, indicating that the melody will loop
|
||||
* indefinitely.
|
||||
*
|
||||
* \sa setLoopCount(), setLoopDuration(), play()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void Melody::setLoopCount(int count)
|
||||
* \brief Sets the number of times the melody should loop to \a count.
|
||||
*
|
||||
* If \a count is zero, then the melody will loop indefinitely.
|
||||
*
|
||||
* \sa loopCount(), setLoopDuration()
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Sets the maximum number of loops to last no longer than \a ms milliseconds.
|
||||
*
|
||||
* This function must be called after the melody is specified with setMelody()
|
||||
* as it uses the length of the melody and \a ms to determine the loopCount().
|
||||
*
|
||||
* \sa loopCount(), setLoopCount()
|
||||
*/
|
||||
void Melody::setLoopDuration(unsigned long ms)
|
||||
{
|
||||
unsigned long duration = 0;
|
||||
for (unsigned int index = 0; index < size; ++index)
|
||||
duration += (1000 / lengths[index]) * 13 / 10;
|
||||
_loopCount = (int)(ms / duration);
|
||||
if (!_loopCount)
|
||||
_loopCount = 1; // Play the melody at least once.
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Starts playing the melody, or restarts it if already playing.
|
||||
*
|
||||
* \sa setMelody(), stop(), loopCount()
|
||||
*/
|
||||
void Melody::play()
|
||||
{
|
||||
stop();
|
||||
if (size == 0)
|
||||
return; // No melody to play.
|
||||
loopsLeft = _loopCount;
|
||||
posn = 0;
|
||||
playing = true;
|
||||
nextNote();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Stops playing the melody.
|
||||
*
|
||||
* \sa play()
|
||||
*/
|
||||
void Melody::stop()
|
||||
{
|
||||
if (!playing)
|
||||
return;
|
||||
playing = false;
|
||||
noTone(_pin);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets the melody to the \a size elements of \a notes and \a lengths.
|
||||
*
|
||||
* If a melody is currently playing, then this function will stop playback.
|
||||
*
|
||||
* The \a notes array contains the frequency of the notes to be played,
|
||||
* with the special value \c NOTE_REST indicating a rest where no notes
|
||||
* are playing. The \a lengths array contains the lengths of each of the
|
||||
* notes; a value of 4 indicates a quarter note, a value of 8 indicates
|
||||
* an eighth note, etc.
|
||||
*
|
||||
* \sa play()
|
||||
*/
|
||||
void Melody::setMelody(const int *notes, const uint8_t *lengths, unsigned int size)
|
||||
{
|
||||
stop();
|
||||
this->notes = notes;
|
||||
this->lengths = lengths;
|
||||
this->size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Runs the melody control loop.
|
||||
*
|
||||
* This function must be called by the application's main <tt>loop()</tt>
|
||||
* function to cause the melody to advance from note to note. It will not
|
||||
* block the application while notes are playing.
|
||||
*/
|
||||
void Melody::run()
|
||||
{
|
||||
if (!playing)
|
||||
return;
|
||||
if ((millis() - startNote) >= duration) {
|
||||
noTone(_pin);
|
||||
nextNote();
|
||||
}
|
||||
}
|
||||
|
||||
void Melody::nextNote()
|
||||
{
|
||||
if (posn >= size) {
|
||||
if (loopsLeft != 0 && --loopsLeft <= 0) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
posn = 0;
|
||||
}
|
||||
duration = 1000 / lengths[posn];
|
||||
if (notes[posn] != NOTE_REST)
|
||||
tone(_pin, notes[posn], duration);
|
||||
++posn;
|
||||
duration = duration * 13 / 10; // i.e., duration * 1.3
|
||||
startNote = millis();
|
||||
}
|
155
libraries/Melody/Melody.h
Normal file
155
libraries/Melody/Melody.h
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Southern Storm Software, Pty Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Melody_h
|
||||
#define Melody_h
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
// Note frequencies from http://arduino.cc/en/Tutorial/Tone
|
||||
#define NOTE_B0 31
|
||||
#define NOTE_C1 33
|
||||
#define NOTE_CS1 35
|
||||
#define NOTE_D1 37
|
||||
#define NOTE_DS1 39
|
||||
#define NOTE_E1 41
|
||||
#define NOTE_F1 44
|
||||
#define NOTE_FS1 46
|
||||
#define NOTE_G1 49
|
||||
#define NOTE_GS1 52
|
||||
#define NOTE_A1 55
|
||||
#define NOTE_AS1 58
|
||||
#define NOTE_B1 62
|
||||
#define NOTE_C2 65
|
||||
#define NOTE_CS2 69
|
||||
#define NOTE_D2 73
|
||||
#define NOTE_DS2 78
|
||||
#define NOTE_E2 82
|
||||
#define NOTE_F2 87
|
||||
#define NOTE_FS2 93
|
||||
#define NOTE_G2 98
|
||||
#define NOTE_GS2 104
|
||||
#define NOTE_A2 110
|
||||
#define NOTE_AS2 117
|
||||
#define NOTE_B2 123
|
||||
#define NOTE_C3 131
|
||||
#define NOTE_CS3 139
|
||||
#define NOTE_D3 147
|
||||
#define NOTE_DS3 156
|
||||
#define NOTE_E3 165
|
||||
#define NOTE_F3 175
|
||||
#define NOTE_FS3 185
|
||||
#define NOTE_G3 196
|
||||
#define NOTE_GS3 208
|
||||
#define NOTE_A3 220
|
||||
#define NOTE_AS3 233
|
||||
#define NOTE_B3 247
|
||||
#define NOTE_C4 262
|
||||
#define NOTE_CS4 277
|
||||
#define NOTE_D4 294
|
||||
#define NOTE_DS4 311
|
||||
#define NOTE_E4 330
|
||||
#define NOTE_F4 349
|
||||
#define NOTE_FS4 370
|
||||
#define NOTE_G4 392
|
||||
#define NOTE_GS4 415
|
||||
#define NOTE_A4 440
|
||||
#define NOTE_AS4 466
|
||||
#define NOTE_B4 494
|
||||
#define NOTE_C5 523
|
||||
#define NOTE_CS5 554
|
||||
#define NOTE_D5 587
|
||||
#define NOTE_DS5 622
|
||||
#define NOTE_E5 659
|
||||
#define NOTE_F5 698
|
||||
#define NOTE_FS5 740
|
||||
#define NOTE_G5 784
|
||||
#define NOTE_GS5 831
|
||||
#define NOTE_A5 880
|
||||
#define NOTE_AS5 932
|
||||
#define NOTE_B5 988
|
||||
#define NOTE_C6 1047
|
||||
#define NOTE_CS6 1109
|
||||
#define NOTE_D6 1175
|
||||
#define NOTE_DS6 1245
|
||||
#define NOTE_E6 1319
|
||||
#define NOTE_F6 1397
|
||||
#define NOTE_FS6 1480
|
||||
#define NOTE_G6 1568
|
||||
#define NOTE_GS6 1661
|
||||
#define NOTE_A6 1760
|
||||
#define NOTE_AS6 1865
|
||||
#define NOTE_B6 1976
|
||||
#define NOTE_C7 2093
|
||||
#define NOTE_CS7 2217
|
||||
#define NOTE_D7 2349
|
||||
#define NOTE_DS7 2489
|
||||
#define NOTE_E7 2637
|
||||
#define NOTE_F7 2794
|
||||
#define NOTE_FS7 2960
|
||||
#define NOTE_G7 3136
|
||||
#define NOTE_GS7 3322
|
||||
#define NOTE_A7 3520
|
||||
#define NOTE_AS7 3729
|
||||
#define NOTE_B7 3951
|
||||
#define NOTE_C8 4186
|
||||
#define NOTE_CS8 4435
|
||||
#define NOTE_D8 4699
|
||||
#define NOTE_DS8 4978
|
||||
|
||||
// Special note value that indicates a rest.
|
||||
#define NOTE_REST 0
|
||||
|
||||
class Melody {
|
||||
public:
|
||||
Melody(uint8_t pin);
|
||||
|
||||
bool isPlaying() const { return playing; }
|
||||
|
||||
int loopCount() const { return _loopCount; }
|
||||
void setLoopCount(int count) { _loopCount = count; }
|
||||
|
||||
void setLoopDuration(unsigned long ms);
|
||||
|
||||
void play();
|
||||
void stop();
|
||||
|
||||
void setMelody(const int *notes, const uint8_t *lengths, unsigned int size);
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
uint8_t _pin;
|
||||
bool playing;
|
||||
int _loopCount;
|
||||
int loopsLeft;
|
||||
const int *notes;
|
||||
const uint8_t *lengths;
|
||||
unsigned int size;
|
||||
unsigned int posn;
|
||||
unsigned long duration;
|
||||
unsigned long startNote;
|
||||
|
||||
void nextNote();
|
||||
};
|
||||
|
||||
#endif
|
19
libraries/Melody/examples/PlayTone/PlayTone.pde
Normal file
19
libraries/Melody/examples/PlayTone/PlayTone.pde
Normal file
@ -0,0 +1,19 @@
|
||||
#include <Melody.h>
|
||||
|
||||
int notes[] = {
|
||||
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3,
|
||||
NOTE_REST, NOTE_B3, NOTE_C4, NOTE_REST
|
||||
};
|
||||
byte lengths[] = {4, 8, 8, 4, 4, 4, 4, 4, 2};
|
||||
|
||||
Melody melody(8);
|
||||
|
||||
void setup() {
|
||||
melody.setMelody(notes, lengths, sizeof(lengths));
|
||||
melody.setLoopCount(3);
|
||||
melody.play();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
melody.run();
|
||||
}
|
8
libraries/Melody/keywords.txt
Normal file
8
libraries/Melody/keywords.txt
Normal file
@ -0,0 +1,8 @@
|
||||
Melody KEYWORD1
|
||||
|
||||
play KEYWORD2
|
||||
stop KEYWORD2
|
||||
setMelody KEYWORD2
|
||||
loopCount KEYWORD2
|
||||
setLoopCount KEYWORD2
|
||||
isPlaying KEYWORD2
|
Loading…
x
Reference in New Issue
Block a user