Hi all,
I'm experimenting with Timer 1 on my MEGA2560 R3 and want to either download or generate simple music note data. For example, here's one I put together (to explain what I'm talking about):
const uint16_t notes[] = {
NOTE_C4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_C4, NOTE_E4, NOTE_D4, NOTE_G3,
NOTE_C4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_C4, NOTE_B3, NOTE_C4, NOTE_C4,
NOTE_D4, NOTE_E4, NOTE_F4, NOTE_E4, NOTE_D4, NOTE_C4, NOTE_B3, NOTE_G3,
NOTE_A3, NOTE_B3, NOTE_C4, NOTE_C4, NOTE_A4, NOTE_B4, NOTE_A4, NOTE_G4,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_E4,
NOTE_G4, NOTE_A4, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5,
NOTE_A4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_D5, NOTE_C5, NOTE_C5,
};
const uint8_t duration[] = {
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 4, 4, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 4, 4, 3, 1, 2, 2,
2, 2, 4, 3, 1, 2, 2, 4,
4, 3, 1, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 4, 4,
};
The notes are frequency defines (i.e. NOTE_A4 is 440, etc..) and the duration is based on note timing multiplied by a constant to determine music speed. (The song is, by the way, "Yankee Doodle" (or the "Barney" song or if you're old enough to remember, the "Roger Ramjet" song)
Anyway, I made the above data from sheet music, laboriously figuring it out note by note (because I don't read music).
I've tried searching for "convert notes to frequencies" and "convert midi to raw data" and all other kinds of things and came up with nothing.
If anyone can point me in a direction to easily obtain a few larger test files like this, I would appreciate it.
The format doesn't have to be exact... I can convert it as long as I have note and timing info.
Thanks!
(p.s. here's the whole thing for anyone who wants to play with it):
// note defines stolen from "Tone.h"
#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 PIEZO_A 2 // pins for the beeper/speaker
#define PIEZO_B 3
// bigger songs should be in PROGMEM!
const uint16_t notes[] = {
NOTE_C4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_C4, NOTE_E4, NOTE_D4, NOTE_G3,
NOTE_C4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_C4, NOTE_B3, NOTE_C4, NOTE_C4,
NOTE_D4, NOTE_E4, NOTE_F4, NOTE_E4, NOTE_D4, NOTE_C4, NOTE_B3, NOTE_G3,
NOTE_A3, NOTE_B3, NOTE_C4, NOTE_C4, NOTE_A4, NOTE_B4, NOTE_A4, NOTE_G4,
NOTE_A4, NOTE_B4, NOTE_C5, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_F4, NOTE_E4,
NOTE_G4, NOTE_A4, NOTE_B4, NOTE_A4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5,
NOTE_A4, NOTE_G4, NOTE_C5, NOTE_B4, NOTE_D5, NOTE_C5, NOTE_C5,
};
const uint8_t duration[] = {
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 4, 4, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 4, 4, 3, 1, 2, 2,
2, 2, 4, 3, 1, 2, 2, 4,
4, 3, 1, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 4, 4,
};
uint8_t BUZ_BIT1;
uint8_t BUZ_BIT2;
volatile uint8_t *BUZ_PORT1;
volatile uint8_t *BUZ_PORT2;
volatile uint8_t *BUZ_DDR1;
volatile uint8_t *BUZ_DDR2;
volatile uint8_t state;
ISR (TIMER1_COMPA_vect)
{
// toggle piezo pins alternately
// __ __ __ __
// PIEZO_A _| |__| |__| |__|
// _ __ __ __
// PIEZO_B |__| |__| |__| |__
//
(state % 2) ? *BUZ_PORT1 |= BUZ_BIT1 : *BUZ_PORT1 &= ~BUZ_BIT1;
(state++ % 2) ? *BUZ_PORT2 &= ~BUZ_BIT2 : *BUZ_PORT2 |= BUZ_BIT2;
}
void playnote (uint32_t freq)
{
uint8_t ps = 0;
if (freq) { // freq==0 turns off timer
ps++;
freq = (F_CPU / (freq * 2));
while (freq > 0xFFFF) { // calculate divider
freq /= 8;
ps++;
}
}
// set timer 1 (16 bit)
TCCR1A = 0;
TCCR1B = _BV (WGM12) | ps; // mode 4 (CTC) | prescaler
OCR1A = freq;
TIMSK1 = _BV (OCIE1A); // enable interrupt on OCA match
}
int main (void)
{
#define SPD 100 // arbitrary delay
init ();
Serial.begin (115200);
BUZ_BIT1 = digitalPinToBitMask (PIEZO_A);
BUZ_BIT2 = digitalPinToBitMask (PIEZO_B);
BUZ_PORT1 = portOutputRegister (digitalPinToPort (PIEZO_A));
BUZ_PORT2 = portOutputRegister (digitalPinToPort (PIEZO_B));
BUZ_DDR1 = portModeRegister (digitalPinToPort (PIEZO_A));
BUZ_DDR2 = portModeRegister (digitalPinToPort (PIEZO_B));
*BUZ_DDR1 |= BUZ_BIT1; // set DDR to output
*BUZ_DDR2 |= BUZ_BIT2;
uint8_t n, x;
n = sizeof (notes) / sizeof (*notes);
for (x = 0; x < n; x++) {
playnote (notes[x]);
_delay_ms (SPD * duration[x]); // 60 is an arbitrary delay
playnote (0);
_delay_ms (SPD);
}
while (1);
}