Skip to content

Instantly share code, notes, and snippets.

@scazon
Created July 14, 2015 15:53
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save scazon/9bb7daab2d1a8342ade3 to your computer and use it in GitHub Desktop.
Save scazon/9bb7daab2d1a8342ade3 to your computer and use it in GitHub Desktop.
GBDK music player
/* Here's a look at how I created a quick music player for use with GBDK.
It basically defines how to play a note, and then stores an array of notes
to be played as a timer interates through the beats */
//Define note names
typedef enum {
C3, Cd3, D3, Dd3, E3, F3, Fd3, G3, Gd3, A3, Ad3, B3,
C4, Cd4, D4, Dd4, E4, F4, Fd4, G4, Gd4, A4, Ad4, B4,
C5, Cd5, D5, Dd5, E5, F5, Fd5, G5, Gd5, A5, Ad5, B5,
C6, Cd6, D6, Dd6, E6, F6, Fd6, G6, Gd6, A6, Ad6, B6,
C7, Cd7, D7, Dd7, E7, F7, Fd7, G7, Gd7, A7, Ad7, B7,
C8, Cd8, D8, Dd8, E8, F8, Fd8, G8, Gd8, A8, Ad8, B8,
SILENCE
} pitch;
const UWORD frequencies[] = { //values based on a formula used by the GB processor
44, 156, 262, 363, 457, 547, 631, 710, 786, 854, 923, 986,
1046, 1102, 1155, 1205, 1253, 1297, 1339, 1379, 1417, 1452, 1486, 1517,
1546, 1575, 1602, 1627, 1650, 1673, 1694, 1714, 1732, 1750, 1767, 1783,
1798, 1812, 1825, 1837, 1849, 1860, 1871, 1881, 1890, 1899, 1907, 1915,
1923, 1930, 1936, 1943, 1949, 1954, 1959, 1964, 1969, 1974, 1978, 1982,
1985, 1988, 1992, 1995, 1998, 2001, 2004, 2006, 2009, 2011, 2013, 2015,
0
};
//Define Instrument names
//Instruments should be confined to one channel
//due to different registers used between ch1, 2, 3, 4
typedef enum {
NONE,
MELODY, //channel 1
HARMONY, //channel 1
SNARE, //channel 4
CYMBAL //channel 4
} instrument;
//Define a note as having a pitch, instrument, and volume envelope
typedef struct {
instrument i;
pitch p;
UBYTE env;
} note;
//define a song as a series of note structs
//This song is a 16 note loop on channel 1
//each channel should have its own array, so
//that multiple notes can be played simultaneously
note song_ch1[16] = { //notes to be played on channel 1
{MELODY, A5, 0x81U},
{MELODY, C5, 0xA2U},
{MELODY, E5, 0x81U},
{MELODY, Gd5, 0x84U},
{HARMONY, C4, 0x81U},
{HARMONY, E7, 0x87U},
{MELODY, C6, 0x81U},
{NONE, SILENCE, 0x00U},
{NONE, SILENCE, 0x00U},
{MELODY, E4, 0x81U},
{MELODY, F4, 0x84U},
{HARMONY, G5, 0x81U},
{NONE, SILENCE, 0x00U},
{MELODY, F5, 0x84U},
{HARMONY, B4, 0x81U},
{NONE, SILENCE, 0x00U},
{NONE, SILENCE, 0x00U}
};
//function to set sound registers based on notes chosen
void setNote(note *n){
switch((*n).i){
case MELODY:
NR10_REG = 0x00U; //pitch sweep
NR11_REG = 0x84U; //wave duty
NR12_REG = (*n).env; //envelope
NR13_REG = (UBYTE)frequencies[(*n).p]; //low bits of frequency
NR14_REG = 0x80U | ((UWORD)frequencies[(*n).p]>>8); //high bits of frequency (and sound reset)
break;
case HARMONY:
NR10_REG = 0x01U;
NR11_REG = 0x00U; //wave duty for harmony is different
NR12_REG = (*n).env;
NR13_REG = (UBYTE)frequencies[(*n).p];
NR14_REG = 0x80U | ((UWORD)frequencies[(*n).p]>>8);
break;
case SNARE:
break;
case CYMBAL:
break;
}
}
//This function plays whatever note is on
//the current beat in Channel 1
void playChannel1(){
setNote(&song_ch1[currentBeat]);
NR51_REG |= 0x11U; //enable sound on channel 1
}
//Timer function gets called 16 times a second
void timerInterrupt(){
if (timerCounter == 4){ //every 4 ticks is a beat, or 4 beats per second
timerCounter=0;
currentBeat = currentBeat == 15 ? 0 : currentBeat+1;
playChannel1(); //every beat, play the sound for that beat
//playChannel2(); make more functions to play sounds on
//playChannel3(); the other channels
//playChannel4();
}
timerCounter++;
}
/*To have more notes playing simultaneously, i'd need
to make up to three more note arrays, song_ch2, song_ch3, song_ch4,
add new playChannel1/2/3() functions, and add them to the timer interrupt
If there are multiple songs, I can change the playChannel1() function to
refer to a pointer to the 'active song' array, and then change the active
array based on which song is supposed to be playing.
*/
@kanfor
Copy link

kanfor commented Mar 19, 2016

Thanks you very much!!!
Works perfectly!

@cansik
Copy link

cansik commented May 31, 2016

Can't get it to work. What else do I need to play the song?

@koopthekoopa
Copy link

Wow! Good job bro

@T0biasCZe
Copy link

how to convert midi to the note format ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment