Skip to content

Instantly share code, notes, and snippets.

@armornick
Created August 24, 2012 07:31
Show Gist options
  • Save armornick/3447121 to your computer and use it in GitHub Desktop.
Save armornick/3447121 to your computer and use it in GitHub Desktop.
Play a sound with SDL2 (no SDL_Mixer)
#include <SDL2/SDL.h>
#define MUS_PATH "Roland-GR-1-Trumpet-C5.wav"
// prototype for our audio callback
// see the implementation for more information
void my_audio_callback(void *userdata, Uint8 *stream, int len);
// variable declarations
static Uint8 *audio_pos; // global pointer to the audio buffer to be played
static Uint32 audio_len; // remaining length of the sample we have to play
/*
** PLAYING A SOUND IS MUCH MORE COMPLICATED THAN IT SHOULD BE
*/
int main(int argc, char* argv[]){
// Initialize SDL.
if (SDL_Init(SDL_INIT_AUDIO) < 0)
return 1;
// local variables
static Uint32 wav_length; // length of our sample
static Uint8 *wav_buffer; // buffer containing our audio file
static SDL_AudioSpec wav_spec; // the specs of our piece of music
/* Load the WAV */
// the specs, length and buffer of our wav are filled
if( SDL_LoadWAV(MUS_PATH, &wav_spec, &wav_buffer, &wav_length) == NULL ){
return 1;
}
// set the callback function
wav_spec.callback = my_audio_callback;
wav_spec.userdata = NULL;
// set our global static variables
audio_pos = wav_buffer; // copy sound buffer
audio_len = wav_length; // copy file length
/* Open the audio device */
if ( SDL_OpenAudio(&wav_spec, NULL) < 0 ){
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
exit(-1);
}
/* Start playing */
SDL_PauseAudio(0);
// wait until we're don't playing
while ( audio_len > 0 ) {
SDL_Delay(100);
}
// shut everything down
SDL_CloseAudio();
SDL_FreeWAV(wav_buffer);
}
// audio callback function
// here you have to copy the data of your audio buffer into the
// requesting audio buffer (stream)
// you should only copy as much as the requested length (len)
void my_audio_callback(void *userdata, Uint8 *stream, int len) {
if (audio_len ==0)
return;
len = ( len > audio_len ? audio_len : len );
//SDL_memcpy (stream, audio_pos, len); // simply copy from one buffer into the other
SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);// mix from one buffer into another
audio_pos += len;
audio_len -= len;
}
@tinnnysu
Copy link

tinnnysu commented Dec 8, 2016

Good example! But before mix audio, I think that it's better make destination buffer silence, or it may make new programmer like me confused.
SDL_memset(stream, 0, len);

@frranck
Copy link

frranck commented Jan 11, 2017

Is there a simple example on how to change the tone ?

@spencerkohan
Copy link

Why does this play the sample for every call of my_audio_callback for me?

@jordanhalase
Copy link

jordanhalase commented May 13, 2017

There is a race condition on line 75 and line 51 where the main thread checks audio_len as the audio thread writes to it.

It (probably) doesn't matter in this tiny example, but audio_len should be atomic. SDL already provides this as SDL_atomic_t.

@Aurel300
Copy link

@jordanhalase A race condition can usually have adverse effects. In this case, the worst thing that can happen is that the waiting thread reads an older value, so it waits a bit longer than it should. Given that the waiting is achieved with 100ms delays (i.e. the program doesn't guarantee to terminate as soon as the sound finished playing), this is really fine.

@sarakh1999
Copy link

great

@alikmr
Copy link

alikmr commented Jan 31, 2019

how i can make it repeat for many times?

@nesteruk
Copy link

This doesn't work for me. Instead of playing the sound once, it fails to play it on first call, then plays it about 5 times when I call this again.

@matozoid
Copy link

Works great, but I think it would be better to have line 72 commented instead of line 71, since I thought everything was broken :-)

@NguyenMVo
Copy link

NguyenMVo commented Apr 15, 2020

The code doesn't work for me. It's keep repeating the first few seconds over and over . Can anyone help me ? (I'm using SDL 2.0.12 with Code::Blocks 17.12)

@htmlcsjs
Copy link

Same thing happend to me @NguyenMVo

@armornick
Copy link
Author

I haven't touched this code in years, so I can't help anyone with their problems. Personally, I would suggest using SDL_Mixer or something more modern like SFML or raylib.

@Axilot
Copy link

Axilot commented Sep 26, 2020

I haven't touched this code in years, so I can't help anyone with their problems. Personally, I would suggest using SDL_Mixer or something more modern like SFML or raylib.

Can i use vulkan to render my windows in raylib?

@its-theo
Copy link

oh god thats a lot of code xD

@alpheratz0
Copy link

Thanks!!

@haojie1
Copy link

haojie1 commented Jun 11, 2023

Works great, but I think it would be better to have line 72 commented instead of line 71, since I thought everything was broken :-)

Agree!!!, Commenting line 72 makes a lot noise for me.

@lskjdkf
Copy link

lskjdkf commented Dec 9, 2023

Since SDL 2.0.4 you can use SDL_QueueAudio to not use callbacks

SDL_AudioSpec spec;
Uint8 *data;
Uint32 len;
SDL_LoadWAV("sound.wav", &spec, &data, &len);
SDL_OpenAudio(&spec, NULL);
SDL_QueueAudio(1, data, len);
SDL_PauseAudio(0);

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