|
| 1 | +/* |
| 2 | + * This example code creates a mixer, loads a single sound, and plays it, with |
| 3 | + * several playback options (fade-in, loop, etc). |
| 4 | + * |
| 5 | + * This code is public domain. Feel free to use it for any purpose! |
| 6 | + */ |
| 7 | + |
| 8 | +#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */ |
| 9 | +#include <SDL3/SDL.h> |
| 10 | +#include <SDL3/SDL_main.h> |
| 11 | +#include <SDL3_mixer/SDL_mixer.h> |
| 12 | + |
| 13 | +/* We will use this renderer to draw into this window every frame. */ |
| 14 | +static SDL_Window *window = NULL; |
| 15 | +static SDL_Renderer *renderer = NULL; |
| 16 | +static MIX_Mixer *mixer = NULL; |
| 17 | +static MIX_Track *track = NULL; |
| 18 | + |
| 19 | +/* This function runs once at startup. */ |
| 20 | +SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) |
| 21 | +{ |
| 22 | + char *path = NULL; |
| 23 | + MIX_Audio *audio = NULL; |
| 24 | + SDL_PropertiesID options = 0; |
| 25 | + |
| 26 | + SDL_SetAppMetadata("Example Play With Options", "1.0", "com.example.play-with-options"); |
| 27 | + |
| 28 | + /* this doesn't have to run very much, so give up tons of CPU time between iterations. Optional! */ |
| 29 | + SDL_SetHint(SDL_HINT_MAIN_CALLBACK_RATE, "5"); |
| 30 | + |
| 31 | + /* we don't need video, but we'll make a window for smooth operation. */ |
| 32 | + if (!SDL_Init(SDL_INIT_VIDEO)) { |
| 33 | + SDL_Log("Couldn't initialize SDL: %s", SDL_GetError()); |
| 34 | + return SDL_APP_FAILURE; |
| 35 | + } |
| 36 | + |
| 37 | + if (!SDL_CreateWindowAndRenderer("examples/basic/play-with-options", 640, 480, SDL_WINDOW_RESIZABLE, &window, &renderer)) { |
| 38 | + SDL_Log("Couldn't create window/renderer: %s", SDL_GetError()); |
| 39 | + return SDL_APP_FAILURE; |
| 40 | + } |
| 41 | + |
| 42 | + if (!MIX_Init()) { |
| 43 | + SDL_Log("Couldn't init SDL_mixer library: %s", SDL_GetError()); |
| 44 | + return SDL_APP_FAILURE; |
| 45 | + } |
| 46 | + |
| 47 | + /* Create a mixer on the default audio device. Don't care about the specific audio format. */ |
| 48 | + mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL); |
| 49 | + if (!mixer) { |
| 50 | + SDL_Log("Couldn't create mixer on default device: %s", SDL_GetError()); |
| 51 | + return SDL_APP_FAILURE; |
| 52 | + } |
| 53 | + |
| 54 | + /* load a sound file */ |
| 55 | + SDL_asprintf(&path, "%smusic.mp3", SDL_GetBasePath()); /* allocate a string of the full file path */ |
| 56 | + audio = MIX_LoadAudio(mixer, path, false); |
| 57 | + if (!audio) { |
| 58 | + SDL_Log("Couldn't load %s: %s", path, SDL_GetError()); |
| 59 | + SDL_free(path); |
| 60 | + return SDL_APP_FAILURE; |
| 61 | + } |
| 62 | + |
| 63 | + SDL_free(path); /* done with this, the file is loaded. */ |
| 64 | + |
| 65 | + /* we need a track on the mixer to play the audio. Each track has audio assigned to it, and |
| 66 | + all playing tracks are mixed together for the final output. */ |
| 67 | + |
| 68 | + track = MIX_CreateTrack(mixer); |
| 69 | + if (!track) { |
| 70 | + SDL_Log("Couldn't create a mixer track: %s", SDL_GetError()); |
| 71 | + return SDL_APP_FAILURE; |
| 72 | + } |
| 73 | + MIX_SetTrackAudio(track, audio); |
| 74 | + |
| 75 | + /* start the audio playing! */ |
| 76 | + options = SDL_CreateProperties(); |
| 77 | + if (!options) { |
| 78 | + SDL_Log("Couldn't create play options: %s", SDL_GetError()); |
| 79 | + return SDL_APP_FAILURE; |
| 80 | + } |
| 81 | + |
| 82 | + /* note these all use MILLISECONDS, since the track is generic, but you can use equivalent FRAMES properties, for frame-perfect mixing. */ |
| 83 | + SDL_SetNumberProperty(options, MIX_PROP_PLAY_START_MILLISECOND_NUMBER, 1000); /* start the first loop 1 second into the audio. */ |
| 84 | + SDL_SetNumberProperty(options, MIX_PROP_PLAY_MAX_MILLISECONDS_NUMBER, 10000); /* play at most 10 seconds of audio before ending/looping (since we started 1000 in, this will be the eleventh second). */ |
| 85 | + SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOPS_NUMBER, 2); /* loop 2 times, 3rd time through doesn't loop. */ |
| 86 | + SDL_SetNumberProperty(options, MIX_PROP_PLAY_LOOP_START_MILLISECOND_NUMBER, 2000); /* when looping, start again here instead of the start of the track. */ |
| 87 | + SDL_SetNumberProperty(options, MIX_PROP_PLAY_FADE_IN_MILLISECONDS_NUMBER, 5000); /* fade-in the first loop over five seconds. No fade on the loops, unless the initial fade is still in progress! */ |
| 88 | + MIX_PlayTrack(track, options); |
| 89 | + SDL_DestroyProperties(options); /* MIX_PlayTrack makes a copy of the options, so this can go away. */ |
| 90 | + |
| 91 | + /* we don't save `audio`; SDL_mixer will clean it up for us during MIX_Quit(). */ |
| 92 | + |
| 93 | + return SDL_APP_CONTINUE; /* carry on with the program! */ |
| 94 | +} |
| 95 | + |
| 96 | +/* This function runs when a new event (mouse input, keypresses, etc) occurs. */ |
| 97 | +SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) |
| 98 | +{ |
| 99 | + if (event->type == SDL_EVENT_QUIT) { |
| 100 | + return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ |
| 101 | + } |
| 102 | + return SDL_APP_CONTINUE; /* carry on with the program! */ |
| 103 | +} |
| 104 | + |
| 105 | +/* This function runs once per frame, and is the heart of the program. */ |
| 106 | +SDL_AppResult SDL_AppIterate(void *appstate) |
| 107 | +{ |
| 108 | + /* draw a blank video frame to keep the OS happy */ |
| 109 | + SDL_RenderClear(renderer); |
| 110 | + SDL_RenderPresent(renderer); |
| 111 | + |
| 112 | + /* when the track has finished playing, end the program. */ |
| 113 | + if (!MIX_TrackPlaying(track)) { |
| 114 | + return SDL_APP_SUCCESS; |
| 115 | + } |
| 116 | + |
| 117 | + return SDL_APP_CONTINUE; /* carry on with the program! */ |
| 118 | +} |
| 119 | + |
| 120 | +/* This function runs once at shutdown. */ |
| 121 | +void SDL_AppQuit(void *appstate, SDL_AppResult result) |
| 122 | +{ |
| 123 | + /* SDL will clean up the window/renderer for us, MIX_Quit() destroys any mixer objects we made. */ |
| 124 | + MIX_Quit(); |
| 125 | +} |
| 126 | + |
0 commit comments