diff options
Diffstat (limited to 'experiments/soundfont_from_file.c')
| -rw-r--r-- | experiments/soundfont_from_file.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/experiments/soundfont_from_file.c b/experiments/soundfont_from_file.c new file mode 100644 index 0000000..8518744 --- /dev/null +++ b/experiments/soundfont_from_file.c | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | #include "../minisdl_audio.h" | ||
| 2 | |||
| 3 | #define TSF_IMPLEMENTATION | ||
| 4 | #include "../tsf.h" | ||
| 5 | |||
| 6 | // Holds the global instance pointer | ||
| 7 | static tsf* g_TinySoundFont; | ||
| 8 | |||
| 9 | // A Mutex so we don't call note_on/note_off while rendering audio samples | ||
| 10 | static SDL_mutex* g_Mutex; | ||
| 11 | |||
| 12 | static void AudioCallback(void* data, Uint8 *stream, int len) { | ||
| 13 | // Render the audio samples in float format | ||
| 14 | int SampleCount = (len / (2 * sizeof(float))); //2 output channels | ||
| 15 | SDL_LockMutex(g_Mutex); //get exclusive lock | ||
| 16 | tsf_render_float(g_TinySoundFont, (float*)stream, SampleCount, 0); | ||
| 17 | SDL_UnlockMutex(g_Mutex); | ||
| 18 | } | ||
| 19 | |||
| 20 | int main(int argc, char *argv[]) { | ||
| 21 | int i, Notes[7] = { 48, 50, 52, 53, 55, 57, 59 }; | ||
| 22 | |||
| 23 | // Define the desired audio output format we request | ||
| 24 | SDL_AudioSpec OutputAudioSpec; | ||
| 25 | OutputAudioSpec.freq = 44100; | ||
| 26 | OutputAudioSpec.format = AUDIO_F32; | ||
| 27 | OutputAudioSpec.channels = 2; | ||
| 28 | OutputAudioSpec.samples = 4096; | ||
| 29 | OutputAudioSpec.callback = AudioCallback; | ||
| 30 | |||
| 31 | // Initialize the audio system | ||
| 32 | if (SDL_AudioInit(TSF_NULL) < 0) { | ||
| 33 | fprintf(stderr, "Could not initialize audio hardware or driver\n"); | ||
| 34 | return 1; | ||
| 35 | } | ||
| 36 | |||
| 37 | // Load the SoundFont from a file | ||
| 38 | g_TinySoundFont = tsf_load_filename("../soundfonts/florestan-subset.sf2"); | ||
| 39 | if (!g_TinySoundFont) { | ||
| 40 | fprintf(stderr, "Could not load SoundFont\n"); | ||
| 41 | return 1; | ||
| 42 | } | ||
| 43 | |||
| 44 | // Set the SoundFont rendering output mode | ||
| 45 | tsf_set_output(g_TinySoundFont, TSF_STEREO_INTERLEAVED, OutputAudioSpec.freq, 0); | ||
| 46 | |||
| 47 | // Create the mutex | ||
| 48 | g_Mutex = SDL_CreateMutex(); | ||
| 49 | |||
| 50 | // Request the desired audio output format | ||
| 51 | if (SDL_OpenAudio(&OutputAudioSpec, TSF_NULL) < 0) { | ||
| 52 | fprintf(stderr, "Could not open the audio hardware or the desired audio output format\n"); | ||
| 53 | return 1; | ||
| 54 | } | ||
| 55 | |||
| 56 | // Start the actual audio playback here | ||
| 57 | // The audio thread will begin to call our AudioCallback function | ||
| 58 | SDL_PauseAudio(0); | ||
| 59 | |||
| 60 | // Loop through all the presets in the loaded SoundFont | ||
| 61 | for (i = 0; i < tsf_get_presetcount(g_TinySoundFont); i++) { | ||
| 62 | //Get exclusive mutex lock, end the previous note and play a new note | ||
| 63 | printf("Play note %d with preset #%d '%s'\n", Notes[i % 7], i, tsf_get_presetname(g_TinySoundFont, i)); | ||
| 64 | SDL_LockMutex(g_Mutex); | ||
| 65 | tsf_note_off(g_TinySoundFont, i - 1, Notes[(i - 1) % 7]); | ||
| 66 | tsf_note_on(g_TinySoundFont, i, Notes[i % 7], 1.0f); | ||
| 67 | SDL_UnlockMutex(g_Mutex); | ||
| 68 | SDL_Delay(1000); | ||
| 69 | } | ||
| 70 | |||
| 71 | // We could call tsf_close(g_TinySoundFont) and SDL_DestroyMutex(g_Mutex) | ||
| 72 | // here to free the memory and resources but we just let the OS clean up | ||
| 73 | // because the process ends here. | ||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
