Adam:
Part of the problem is that there are many repeated notes in Rhapsody in Blue. I only recently learned that in electronic music, it is customary for the last 1/8 duration of each note to be silent, to mimic the effect of a musician playing two successive (but identical in pitch) notes. Some tunes have few repeated notes, so neglecting this pause is not very noticeable, but it is fatal for Rhapsody in Blue. I’ve sort-of fixed that problem in the code that follows by setting the buzzer port to input for the last 1/8 duration. There don’t seem to be any actual, i.e. programmed, pauses in the tune array. Is this correct?
It sounds better now, but there are still too many weird timings. I think the gimmick of multiplying the duration by 5 (in your first example) and then dividing by 8 for the inter-note pause may be too crude. Could you dispense with the first element of the tune array and re-compile your MIDI source to give the actual note durations in milliseconds (including 1/8 duration pause)?
The version I’ve uploaded here is for the LV-168 with a 20 MHz clock and buzzer on PB2. Try it, I would like to see it work!
Cheers, Jim
/*
Gershwin on the Orangutan
Completely ripped off from Jim Remington's buzzer_tunes2.c
Which, in turn, was ripped off the Butterfly code from Atmel
Somewhat less of a mess, but still not entirely working
-Adam
Now closer
-Jim
*/
// LV-168 with 20 MHz clock and buzzer on PB2.
// Timer constants not changed, so frequencies are too high by factor (20/8)
#define F_CPU 20000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#define p 0 //pause = silence
#define c1 2034
#define cx1 1804
#define d1 1703
#define dx1 1607
#define e1 1517
#define f1 1435
#define fx1 1351
#define g1 1276
#define gx1 1204
#define a1 1136
#define ax1 1073
#define b1 1012
#define c2 956
#define cx2 902
#define d2 851
#define dx2 804
#define e2 758
#define f2 716
#define fx2 676
#define g2 638
#define gx2 602
#define a2 568
#define ax2 536
#define b2 506
#define c3 478
#define cx3 451
#define d3 426
#define dx3 402
#define e3 379
#define f3 358
#define fx3 338
#define g3 319
#define gx3 301
#define a3 284
#define ax3 268
#define b3 253
#define c4 239
#define cx4 225
#define d4 213
#define dx4 201
#define e4 190
#define f4 179
#define fx4 169
#define g4 159
#define gx4 150
#define a4 142
#define ax4 134
#define b4 127
#define c5 119
#define cx5 113
#define d5 106
#define dx5 100
#define e5 95
#define f5 89
#define fx5 84
#define g5 80
#define gx5 75
#define a5 71
#define ax5 67
#define b5 63
#define c6 60
#define cx6 56
#define d6 53
#define dx6 50
#define e6 47
#define f6 45
#define fx6 42
#define g6 40
#define gx6 38
#define a6 36
#define ax6 34
#define b6 32
#define c7 30
const unsigned int tune[] PROGMEM={//RhapsodyInBlue
20,
30,f2,7,g2,9,a2,9,ax2,9,c3,6,d3,9,dx3,7,f3,11,g3,
12,a3,12,ax3,15,c4,16,d4,22,dx4,16,f4,20,g4,29,a4,99,ax4,12,gx4,
10,ax4,20,gx4,40,fx4,40,gx4,40,fx4,40,gx4,40,fx4,60,f4,50,dx4,90,d4,
90,cx4,60,dx4,84,e4,103,f4,73,d4,50,ax3,8,gx3,12,ax3,118,gx3,62,fx3,
51,f3,61,f3,113,f3,37,g3,9,gx3,19,g3,3,gx3,7,g3,45,f3,37,g3,
10,gx3,15,g3,6,gx3,7,g3,45,f3,41,g3,7,gx3,10,g3,10,gx3,10,g3,
57,f3,1,ax3,104,ax3,40,c4,8,cx4,12,c4,7,cx4,11,c4,42,ax3,38,c4,
10,cx4,10,c4,10,cx4,7,c4,45,ax3,38,c4,10,cx4,10,c4,10,cx4,10,c4,
72,ax3,106,dx4,118,dx4,13,f4,13,fx4,13,f4,39,dx4,87,dx5,39,c5,37,f4,
40,fx4,40,g4,40,ax4,40,dx4,50,dx3,60,dx3,60,dx3,90,dx3,45,cx3,45,cx3,
60,cx3,90,cx3,30,dx3,60,dx3,60,dx3,90,dx3,30,fx3,60,fx3,60,fx3,93,fx3,
42,g3,65,dx3,55,c3,75,cx3,60,c3,60,ax2,61,fx2,58,g2,61,ax2,60,g2,
61,dx2,1,dx3,21,f3,19,dx3,19,f3,21,dx3,20,f3,20,dx3,20,f3,10,dx3,
11,f3,10,g3,10,gx3,10,ax3,10,c4,9,cx4,11,dx4,10,f4,10,g4,97,gx4,
8,fx4,12,gx4,20,fx4,40,e4,40,fx4,40,e4,40,fx4,40,e4,60,dx4,60,cx4,
60,c4,100,b3,70,cx4,70,d4,20,dx4,38,c4,62,gx3,118,fx3,62,e3,60,dx3,
20,dx3,100,e2,5,fx2,5,gx2,5,a2,5,b2,5,cx3,5,d3,5,e3,5,fx3,
5,gx3,5,a3,5,b3,5,cx4,5,d4,5,e4,5,fx4,5,gx4,1,a4,99,g4,
21,a4,28,g4,41,f4,40,g4,40,f4,40,g4,40,f4,70,e4,60,d4,60,cx4,
80,c4,100,d4,60,dx4,80,e4,100,cx4,60,a3,75,g3,104,f3,41,e3,60,e3,
20,a4,95,g4,25,a4,30,g4,40,f4,40,g4,40,f4,40,g4,38,f4,72,e4,
60,d4,60,cx4,80,c4,100,d4,60,dx4,80,e4,100,cx4,60,a3,90,g3,90,f3,
40,e3,80,e3,29,e3,29,g3,32,a3,28,g3,42,ax3,60,ax3,49,dx3,29,a3,
32,b3,30,a3,30,cx4,29,dx4,31,b3,30,a3,30,g3,28,ax3,32,c4,28,ax3,
42,cx4,65,cx4,45,fx3,28,c4,32,d4,30,c4,30,e4,28,fx4,32,d4,30,c4,
29,ax3,29,cx4,32,dx4,28,cx4,32,e4,60,e4,60,a3,28,dx4,32,f4,28,dx4,
32,g4,28,a4,32,f4,30,dx4,30,cx4,28,e4,32,fx4,30,e4,29,g4,61,g4,
60,c4,28,fx4,32,gx4,28,fx4,32,ax4,28,c5,32,gx4,30,fx4,30,e4,28,g4,
32,a4,30,g4,28,ax4,62,ax4,60,dx4,28,a4,32,b4,28,a4,32,cx5,30,dx5,
29,b4,31,a4,78,ax4,62,ax4,60,ax4,70,ax4,28,a4,20,gx4,62,gx4,60,gx4,
68,gx4,30,a4,30,ax4,52,ax4,60,ax4,70,ax4,28,c5,22,cx5,60,cx5,60,cx5,
41,cx5,77,g4,62,g4,60,g4,70,g4,28,fx4,20,f4,62,f4,58,f4,72,f4,
28,fx4,30,g4,52,g4,60,g4,70,g4,28,a4,20,ax4,60,ax4,62,ax4,99,ax4,
61,b4,18,g4,62,e4,40,g4,60,f4,60,e4,60,d4,60,ax3,58,b3,62,d4,
58,b3,92,g3,88,ax4,60,b4,60,g4,62,ax4,60,b4,60,d4,60,e4,40,f4,
38,e4,32,d4,8,fx4,30,g4,32,fx4,30,g4,30,fx4,60,g4,60,dx4,60,c4,
61,g3,119,ax3,58,b3,60,g3,60,ax3,62,b3,60,d3,61,e3,37,f3,40,e3,
30,d3,12,fx3,28,g3,32,fx3,30,g3,30,fx3,60,g3,58,e3,63,cx3,60,a2,
117,f3,62,fx3,58,d3,62,f3,60,fx3,60,a2,61,b2,37,c3,42,b2,40,a2,
38,d3,62,d3,20,d3,70,fx4,10,g4,60,g4,60,g4,50,a4,20,g4,30,fx4,
60,f4,20,f4,60,f4,68,f4,32,fx4,60,g4,20,g4,60,g4,70,g4,20,gx4,
10,a4,60,ax4,20,ax4,60,ax4,100,ax4,60,b4,60,g4,48,e4,32,g4,40,f4,
60,e4,60,d4,60,ax3,58,b3,62,d4,60,b3,50,g3,80,fx4,10,g4,60,g4,
60,g4,60,a4,8,g4,32,fx4,60,f4,20,f4,60,f4,70,f4,30,fx4,60,g4,
20,g4,60,g4,70,g4,20,gx4,10,a4,60,ax4,20,ax4,60,ax4,98,ax4,62,b4,
60,g4,48,e4,32,g4,40,f4,60,e4,60,d4,88,ax3,30,b3,62,d4,58,b3,
92,g3,48,a4,62,a4,60,a4,40,b4,30,a4,30,gx4,60,g4,20,g4,60,g4,
68,g4,32,gx4,58,a4,22,a4,58,a4,62,a4,20,ax4,20,b4,60,c5,20,c5,
60,c5,100,c5,60,cx5,60,a4,50,fx4,10,a4,60,g4,60,fx4,60,e4,61,c4,
59,cx4,60,e4,60,cx4,120,a3,120,gx4,20,a4,60,a4,60,a4,50,b4,20,a4,
30,gx4,60,g4,20,g4,60,g4,70,g4,30,gx4,60,a4,20,a4,60,a4,60,a4,
20,ax4,20,b4,60,c5,20,c5,60,c5,100,c5,60,cx5,60,a4,50,fx4,10,a4,
60,g4,60,fx4,60,e4,61,c4,59,cx4,58,e4,62,cx4,60,a3,59,d2,61,e2,
45,g2,13,g2,60,d2,62,e2,50,d2,20,e2,110,f2,38,e2,22,d2,20,a1,
78,b1,80,a1,2,c2,58,d2,62,e2,45,g2,16,g2,58,d2,61,e2,48,d2,
20,e2,92,f2,20,e2,10,f2,49,e2,61,d2,79,a1,81,b1,80,a1,119,c2,
60,d2,61,e2,45,g2,16,g2,58,d2,62,e2,48,d2,19,e2,92,f2,20,e2,
10,f2,49,e2,21,d2,18,c2,22,d2,80,c2,80,b1,80,c2,119,a1,81,b1,
60,c2,60,d2,60,e2,60,fx2,60,g2,60,a2,80,ax2,30,fx2,111,g2,120,ax2,
58,g2,26,ax2,35,fx2,1,g2,120,ax2,58,g2,61,f2,120,f2,119,f2,1,d2,
1,f2,58,fx2,41,g2,40,gx2,40,a2,40,ax2,20,fx2,120,g2,1,ax2,45,g2,
45,c3,30,g2,120,ax2,58,g2,61,f2,118,f2,1,f2,61,d2,
0,0};
unsigned char tempo;
unsigned int tune_index,duration=0,silence=0;
ISR(TIMER0_COMPA_vect){
if(duration>0){
duration--;//keep playing note
if (duration == silence) DDRB=~(1<<PB2); //turn off buzzer output for last 1/8 duration
}else{
tune_index+=2;//increment memory address
duration=tempo*pgm_read_word(tune_index);//read note length
silence = duration>>3; //time for inter-note pause
tune_index+=2;//increment memory address
OCR1A=pgm_read_word(tune_index);//read note freqency
DDRB=(1<<PB2); //set buzzer port to output
if(OCR1A==0){//tune over
TIMSK0&=~(1<<OCIE0A);//disable counter compare interrupts
TIMSK1&=~(1<<OCIE1A);
}
}
}
ISR(TIMER1_COMPA_vect){
PORTB^=(1<<PB2);//Toggle Buzzer
}
int main(void){
// PORTB|=(1<<PB3);
// while(!(PINB&(1<<PB3)));//Wait for button press
DDRB|=(1<<PB2);//Set Buzzer Pin to Output
//Initialize Timer 0
TCCR0A|=(1<<WGM01);//Set CTC mode, OCR0A Top
OCR0A=125;//set OCR0A
TIMSK0|=(1<<OCIE0A);//Enable Compare A interrupt
TCCR0B|=(1<<CS01)|(1<<CS00);//Set 64 prescaler
//Initialize Timer 1
TCCR1B|=(1<<WGM12)|(1<<CS11)|(1<<CS10);//Set CTC Mode, OCR1A Top, 64 prescaler
TIMSK1|=(1<<OCIE1A);//Enable Compare A interrupt
OCR1A|=0xFFFF;//Make OCR1A something other than 0 to start so cycles can occur
tempo=pgm_read_word(tune);//set tempo
tune_index=(int)tune;//point to current tune
sei();
while(1);
return 0;
}