1.2.0 audio problems

My application lets the user toggle audio on and off at run-time, basically
just calling SDL_OpenAudio() and SDL_CloseAudio(). This works fine with
SDL 1.0.8, but using 1.2.0 there’s a problem.

If the user tries to enable audio and the sound card is busy they get the
expected error. When the sound device is free again SDL_OpenAudio() just
fails immediately with the previous error and the application has to be
restarted to get it working again.

An issue under Linux, not sure about Windows because I haven’t got 1.2.0
to cross-compile yet.

Ta.

  • Deth -

My application lets the user toggle audio on and off at run-time, basically
just calling SDL_OpenAudio() and SDL_CloseAudio(). This works fine with
SDL 1.0.8, but using 1.2.0 there’s a problem.

If the user tries to enable audio and the sound card is busy they get the
expected error. When the sound device is free again SDL_OpenAudio() just
fails immediately with the previous error and the application has to be
restarted to get it working again.

Can you post a minimal code sample that we can use to reproduce the
problem?

Thanks!
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

If the user tries to enable audio and the sound card is busy they get the
expected error. When the sound device is free again SDL_OpenAudio() just
fails immediately with the previous error and the application has to be
restarted to get it working again.

Can you post a minimal code sample that we can use to reproduce the
problem?

Okay, here’s the test program, effectively the sample program from the SDL
documentation. Press Return 3 times to hear a sample you provide
(test.wav) 3 times.

Perform the following steps to recreate the problem.

  • Press Return to play the test sample (to confirm that it can be played).
  • Start a sound with another application.
  • Once that’s started, press Return again and you get the “No available
    audio device” error as expected.
  • Stop the external sound.
  • Press Return to trying to play the test sample again. It doesn’t work
    even though the sound device is no longer busy.

As I mentioned before, this works if used with 1.0.8, not under 1.2.0.

Ta.

  • Deth -

=== Makefile ========================================================

CC=gcc
CFLAGS=-Wall -O2 -pipe
SDL_CFLAGS := $(shell sdl-config --cflags)
SDL_LDFLAGS := $(shell sdl-config --libs)

default: test

test: test.c
$(CC) test.c $(CFLAGS) $(SDL_CFLAGS) $(SDL_LDFLAGS) -o test

=== test.c ==========================================================

#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#include <SDL_audio.h>

#define SAMPLE_FILE “test.wav”

#define SYSTEM_ERROR 2

#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

typedef int bool;

/* Global variables. */

Uint8 *Data;
Uint32 Position;
Uint32 Length;

/* Local function prototype. */

static bool Play_Sound();
static void Mix_Audio( void *Unused, Uint8 *Stream, int Length );

/* Main processing. */

int main( int argc, char *argv[] )
{
SDL_AudioSpec AudioSpec;
int Count;

/* Access the SDL library.  */
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
    fprintf( stderr, "Unable to initialise SDL library,\n\t%s\n",
             SDL_GetError() );
    return SYSTEM_ERROR;
}

/* Ensure that SDL is closed when the program ends.  */
if ( atexit( SDL_Quit ) )
{
    perror( "atexit" );
    fprintf( stderr, "Failed to register shut-down handler.\n" );
}

/* Set 16-bit stereo audio at 22Khz.  */
AudioSpec.freq = 22050;
AudioSpec.format = AUDIO_S16;
AudioSpec.channels = 2;
AudioSpec.samples = 512;
AudioSpec.callback = Mix_Audio;
AudioSpec.userdata = NULL;

/* Attempt to play a sample 3 times...  */
for ( Count = 1; Count <= 3; Count++ )
{
    /* Wait for the user to signal that a sound is playing.  */
    printf( "Press Return to play sound.  " );
    fflush( stdout );
    (void) fgetc( stdin );

    /* Open the audio device, display error if unavailable...  */
    if ( SDL_OpenAudio( &AudioSpec, NULL ) < 0 )
    {
        fprintf( stderr, "Unable to open audio.  %s.\n",
                 SDL_GetError() );
    }
    /* Otherwise, if successful...  */
    else
    {
        /* Activate playback.  */
        Length = 0;
        SDL_PauseAudio( 0 );

        /* Load a sample and start it playing.  */
        if ( Play_Sound() )
        {
            return SYSTEM_ERROR;
        }

        /* Deactivate audio device.  */
        SDL_CloseAudio();
    }
}

/* Return successfully.  */
return 0;

}

/* Loads the sample and sets it playing. */

static bool Play_Sound()
{
SDL_AudioSpec Wave;
SDL_AudioCVT Audio;
Uint8 *Buffer;
Uint32 Size;

/* Load the sound file and convert it to the correct frequency.  */
if ( SDL_LoadWAV( SAMPLE_FILE, &Wave, &Buffer, &Size ) == NULL )
{
    fprintf( stderr, "Couldn't load audio file '%s' - %s.\n",
             SAMPLE_FILE, SDL_GetError() );
    return TRUE;
}
if ( SDL_BuildAudioCVT( &Audio, Wave.format, Wave.channels, Wave.freq,
                        AUDIO_S16, 2, 22050 ) != 1 )
{
    fprintf( stderr, "Failed to build audio filter.\n" );
    return TRUE;
}
Audio.buf = malloc( Size * Audio.len_mult );
memcpy( Audio.buf, Buffer, Size );
Audio.len = Size;
SDL_ConvertAudio( &Audio );
SDL_FreeWAV( Buffer );

/* Pass sound data to mixer.  */
SDL_LockAudio();
Data = Audio.buf;
Length = Audio.len_cvt;
Position = 0;
SDL_UnlockAudio();

/* Wait until sample has finished playing.  */
do
{
    SDL_Delay( 1 );
}
while ( Position < Length );

/* Return successfully.  */
return FALSE;

}

/* Combines requested amount of sample data from sound that is playing. */

static void Mix_Audio( void *Unused, Uint8 *Stream, int RequestLength )
{
Uint32 Amount;

/* Determine the amount of sample data to be mixed.  */
Amount = Length - Position;
if ( Amount > RequestLength )
{
    Amount = RequestLength;
}

/* If data is available to be mixed...  */
if ( Amount )
{
    /* Mix the data into a single stream.  */
    SDL_MixAudio( Stream, &Data[ Position ], Amount,
                  SDL_MIX_MAXVOLUME );

    /* Advance sample position.  */
    Position += Amount;
}

}

Can you post a minimal code sample that we can use to reproduce the
problem?

Okay, here’s the test program, effectively the sample program from the SDL
documentation. Press Return 3 times to hear a sample you provide
(test.wav) 3 times.

Has anyone had a chance to look at the code I posted? It’s not a major
issue, but I’d appreciate some feedback.

Ta.

  • Deth -