Starting with some assumptions,
- By keyboard you mean a piano-like keyboard, with which you are able to get the key number that has been pressed.
- The speaker is a conventional speaker attached to a DAC and amp.
- You have small sound tracks that you can play against each key, in .mp3 files.
As indicated in one of the comments, playing an mp3 would be unnecessarily complicated. Instead you can convert the mp3 files into .WAV files, which can be easily read and processed as raw audio signals.
The first thing that you'd wanna make sure is that all the WAV files can be stored into the RAM of the ATMega328. Because reading from the SD card each time would cause a lot of delay. If the files are too big, you can consider:
- Reducing size (hence quality) of each file
- Reducing the total number of files (have 8 keys instead of 24?)
- Having a function that generates the sound signal itself
Now, assuming that there are 8 files and they are stored in an SD card,
they can be read and stored in an array like this before going into a loop
#define NUM_FILES 8 // maximum number of keys
#define MAX_FILE_SIZE 4096 // maximum size of sound files
uint8_t key_sounds[NUM_FILES][MAX_FILE_SIZE];
int main(void)
{
// load sounds from SD card to RAM
for (uint8_t file = 0; file < NUM_FILES; file++)
{
// assuming your files are named like "1.wav"
char file_name[6] = {0};
sprintf(file_name, "%02u.wav", file);
// load data from file_name and copy to relevant key_sounds[]
int err = load_from_sd_card(file_name, key_sounds[file]);
if (err != 0)
{
printf("\rError happened!\n");
return;
}
}
// .... rest of your code, maybe an infinite loop
For your keys, you could have an ISR that reads which key is pressed,
and set a global variable uint8_t key_pressed = 0U
.
void your_isr()
{
key_pressed = read_pressed_key()
}
and for your infinite loop, you can have code that continuously checks if the value of key_pressed
has changed from 0 or not, and when it does, it plays the appropriate sound.
while (true)
{
if (key_pressed != 0U)
{
// in case key_pressed changes during playback
uint8_t key = key_pressed;
// get address of sound data for that key
uint8_t * p_sound = key_sounds[key_pressed];
// send the address of sound data to playback function
play_sound(p_sound);
// reset key_pressed
key_pressed = 0U;
}
}
Do note that this is a very simplified explanation, the code for playing the sound and loading data from SD card is not shown here.