Initializing video kills audio!?

Hi,
I wrote a simple SDL program that loads a .wav specified by the user, and
plays it. That worked fine. Then, I tried to add a second thread to the
program to respond to user input, and the audio stopped working. The program
ran for the right length of time; the callback was being called; the right
values were being written to the stream. There were no errors, no seg fault.
Still, silence.
So I commented out everything I’d added, until I finally found that the
culprit was ORing the SDL_INIT_VIDEO flag with the SDL_INIT_AUDIO flag.
Without the video flag, it works fine. I tried initializing audio separately,
using SDL_InitSubSystem(), but there was still no sound. In both cases,
SDL_WasInit() reports that the audio subsystem was successfully initialized.
I actually don’t need video for my program, but I do need threads and
events, and it’s my understanding that those subsystems are initialized along
with video. Is that the case? I could use PortAudio, but I thought I’d use
SDL audio since I’m using SDL for threads and the SDL_LoadWAV() function.
I’m working on a Pentium 2 running Win2K. This is SDL 1.2.8. I’m
developing/compiling in Dev-C++. I don’t know if it matters, but I believe I
have the latest version of DirectX.
Sorry for the length of this post, but I thought it might be an interesting
enough problem (bug?) that someone might want to think about it. I appreciate
your help!

Thanks,
Anthony

Anthony Kolb <ajkolb hotmail.com> writes:

Hi,
I wrote a simple SDL program that loads a .wav specified by the user, and
plays it. That worked fine. Then, I tried to add a second thread to the
program to respond to user input, and the audio stopped working. The program
ran for the right length of time; the callback was being called; the right
values were being written to the stream. There were no errors, no seg
fault.
Still, silence.
So I commented out everything I’d added, until I finally found that the
culprit was ORing the SDL_INIT_VIDEO flag with the SDL_INIT_AUDIO flag.
Without the video flag, it works fine.
[…]
I’m working on a Pentium 2 running Win2K. This is SDL 1.2.8. I’m
developing/compiling in Dev-C++. I don’t know if it matters, but I believe I
have the latest version of DirectX.

Update:
I tried running the executable generated on my P2 on my laptop (an AMD
Duron, also Win2K), and it had the same problem. I tried compiling the same
code on my laptop, with the same results. The sound cards, etc. are totally
different, so it doesn’t seem like a driver problem.
So, I set Dev-C++ to compile it as a win32 GUI, not a console program, but
the results were (again) the same.
Has anyone run into anything like this before? It’s just happened on two
different platforms, so it can’t just be me. Here is the code in question:

/Begin code/
#include <stdlib.h>
#include <stdio.h>
#include “SDL.h”

void myFreeWAV(void);
void myAudioCallback(void *data, Uint8 *stream, int len);

typedef struct _soundInfo{
Uint8 *sound_buffer;
Uint8 silence;
unsigned length;
unsigned pos;
} soundInfo;

Uint8 *wav_buffer; //This has to be global so myFreeWAV() can access it.

int main(int argc, char *argv[]){
SDL_AudioSpec wav_spec;
Uint8 *temp;
Uint32 num_bytes, subsystem_init;
soundInfo sound;
unsigned i;

if(argc != 2){
fprintf(stderr, “USAGE: “%s (filename.wav)”\n”, argv[0]);
exit(-1);
}

/NOTE: If you uncomment the SDL_INIT_VIDEO flag (below), audio is silenced/
if(SDL_Init(/SDL_INIT_VIDEO |/ SDL_INIT_AUDIO)){
fprintf(stderr, “Could not initialize SDL.\nExiting…\n”);
exit(1);
}
atexit(SDL_Quit);
// SDL_InitSubSystem(SDL_INIT_AUDIO);
subsystem_init=SDL_WasInit(SDL_INIT_EVERYTHING);
if(subsystem_init&SDL_INIT_VIDEO) printf(“Video is initialized.\n”);
else printf(“Video is not initialized.\n”);
if(subsystem_init&SDL_INIT_AUDIO) printf(“Audio is initialized.\n”);
else printf(“Audio is not initialized.\n”);

if( SDL_LoadWAV(argv[1], &wav_spec, &wav_buffer, &num_bytes) == NULL ){
fprintf(stderr, “Could not open %s: %s\n”, argv[1], SDL_GetError());
exit(1);
}
atexit(myFreeWAV);

sound.sound_buffer = wav_buffer;
sound.length = num_bytes;
sound.pos = 0;
sound.silence = wav_spec.silence;
wav_spec.samples = 2048;
wav_spec.callback = myAudioCallback;
wav_spec.userdata = (void *)&sound;
if(SDL_OpenAudio(&wav_spec, NULL)==-1){
fprintf(stderr, “Failed to open audio stream.\nExiting…\n”);
exit(1);
}
atexit(SDL_CloseAudio);
SDL_PauseAudio(0);
while(sound.pos < sound.length){
SDL_Delay(50);
}
SDL_PauseAudio(1);
return 0;
}

// This function simply allows us to register SDL_FreeWAV() with atexit().
void myFreeWAV(void){
SDL_FreeWAV(wav_buffer);
return;
}

/*If there is data left in our sound buffer, it’s written to the stream;
otherwise, silence is written. */
void myAudioCallback(void *data, Uint8 *stream, int len){
unsigned i;
soundInfo *sound;
sound = (soundInfo *)data;
for(i=0; i<len; i++){
if(sound->pos < sound->length){
stream[i] = (sound->sound_buffer)[sound->pos];
sound->pos++;
}
else stream[i] = sound->silence;
}
return;
}
/End code/

There’s a comment that points out where the offending flag is. Note that
the .wav you want to play is passed as a command line argument.
I hope posting a code sample this long isn’t considered bad etiquette. I
know it’s a lot to ask, but if someone compiled it (with the SDL_INIT_VIDEO
flag uncommented!) and it worked, I’d love to know about your setup.
Thanks!

Anthony

I tried running the executable generated on my P2 on my laptop (an AMD
Duron, also Win2K), and it had the same problem. I tried compiling the same
code on my laptop, with the same results. The sound cards, etc. are totally
different, so it doesn’t seem like a driver problem.
So, I set Dev-C++ to compile it as a win32 GUI, not a console program, but
the results were (again) the same.
Has anyone run into anything like this before? It’s just happened on two
different platforms, so it can’t just be me. Here is the code in question:

On Windows, we need to associate DirectSound with a window handle, so
you need to:

  • Initialize with both SDL_INIT_VIDEO and SDL_INIT_AUDIO at the same time.

  • Call SDL_SetVideoMode() before SDL_OpenAudio().

Or it won’t work.

At least, that’s my guess.

Throw an SDL_SetVideoMode(640, 480, 0, 0) in there before the
SDL_OpenAudio call and I bet it starts working again.

Alternately, don’t initialize the video subsystem if you don’t need it.

–ryan.

Ryan C. Gordon <icculus clutteredmind.org> writes:

I tried running the executable generated on my P2 on my laptop (an AMD
Duron, also Win2K), and it had the same problem. I tried compiling the
same

code on my laptop, with the same results. The sound cards, etc. are
totally

different, so it doesn’t seem like a driver problem.
So, I set Dev-C++ to compile it as a win32 GUI, not a console program,
but

the results were (again) the same.
Has anyone run into anything like this before? It’s just happened on
two

different platforms, so it can’t just be me. Here is the code in question:

On Windows, we need to associate DirectSound with a window handle, so
you need to:

  • Initialize with both SDL_INIT_VIDEO and SDL_INIT_AUDIO at the same time.

  • Call SDL_SetVideoMode() before SDL_OpenAudio().

Or it won’t work.

At least, that’s my guess.

Throw an SDL_SetVideoMode(640, 480, 0, 0) in there before the
SDL_OpenAudio call and I bet it starts working again.

Alternately, don’t initialize the video subsystem if you don’t need it.

–ryan.

Ryan,
That did it! Because I wasn’t using any video functions, I never bothered
to create any surfaces. Good catch–I’m impressed!
The question remains: Do I need to initialize video anyway? I don’t want
any graphics, but I do need threads and events. There is no "SDL_INIT_THREADS"
flag, and the documentation seems to imply that events are initialized only
with video. I guess this is something I can experiment with and find out for
myself.
Thanks a ton,

Anthony

The question remains: Do I need to initialize video anyway? I don’t want
any graphics, but I do need threads and events. There is no "SDL_INIT_THREADS"
flag, and the documentation seems to imply that events are initialized only
with video. I guess this is something I can experiment with and find out for
myself.

I think you can probably get away with using SDL threads on Windows
without an init call, but probably not the event system (but I could be
wrong).

Also, OpenAudio should probably fail instead of play silence in the case
you hit earlier…someone should fix that.

–ryan.