Library to play tones and melodies over the DAC.
Dependents: 1620_Project_Template 1620_App_Board_DAC 1620_App_Board_DAC_Melody 1620_Project_Template ... more
Tone.cpp
- Committer:
- eencae
- Date:
- 2017-03-08
- Revision:
- 0:836cdf67dbdb
- Child:
- 1:f17240b3e85e
File content as of revision 0:836cdf67dbdb:
#include "Tone.h" Tone::Tone(PinName dacPin) { dac = new AnalogOut(dacPin); ticker = new Ticker; timeout = new Timeout; note_timeout = new Timeout; } Tone::~Tone() { delete dac; delete[] _sample_array; delete ticker; delete timeout; delete note_timeout; } void Tone::init() { _n = 16; _sample_array = new float[_n]; // create sample array for one period between 0.0 and 1.0 for (int i = 0; i < _n ; i++) { _sample_array[i] = 0.5f + 0.5f*sin(i*2*PI/_n); //printf("y[%i] = %f\n",i,_sample_array[i]); } } void Tone::play(float frequency,float duration) { // calculate time step between samples float dt = 1.0/(frequency*_n); // start from beginning of LUT _sample = 0; // setup ticker and timeout to stop ticker // the ticker repeats every dt to plat each sample in turn ticker->attach(callback(this, &Tone::ticker_isr), dt); // the timeout stops the ticker after the required duration timeout->attach(callback(this, &Tone::timeout_isr), duration ); } void Tone::play_melody(int length,const int *notes,const int *durations,float bpm,bool repeat) { // copy arguments to member variables _bpm = bpm; _notes = notes; // pointer for array _durations = durations; // pointer for array _melody_length = length; _repeat = repeat; _note = 0; // start from first note play_next_note(); // play the next note in the melody } void Tone::play_next_note() { // _note is the note index to play // calculate the duration and frequency of the note float duration = 60.0/(_bpm*_durations[_note]); float frequency = float(_notes[_note]); //printf("[%i] f = %f d = %f\n",_note,frequency,duration); // check if the note is not a space and if not then play the note if (frequency > 0) { play(frequency,duration); } // the timeout goes to the next note in the melody // double the duration to leave a bit of a gap in between notes to be better // able to distinguish them note_timeout->attach(callback(this, &Tone::note_timeout_isr), duration*2.0 ); } // called when the next note needs playing void Tone::note_timeout_isr() { _note++; // go onto next note // if in repeat mode then reset the note counter when get to end of melody if (_repeat && _note == _melody_length) { _note=0; } // check if note is within the melody if (_note < _melody_length) { play_next_note(); } } void Tone::ticker_isr() { dac->write(_sample_array[_sample%_n]); // use modulo to get index to play _sample++; // increment the sample ready for next time } void Tone::timeout_isr() { // stops the ticker to end the note ticker->detach(); }