Fixed SDL 1.2 compatibility problem.
authorSam Lantinga <slouken@libsdl.org>
Sat, 13 Dec 2008 06:36:47 +0000
changeset 2866e532417a6977
parent 2865 09adf4854163
child 2867 eec7adc3d1c5
Fixed SDL 1.2 compatibility problem.

The API specifies that SDL_OpenAudio() will fill out the 'desired' audio spec
with the correct samples and size set by the driver. This value is important
since it may be used by applications that size audio buffers, etc.

However, we want to allow advanced applications to call SDL_OpenAudioDevice()
which gets passed a const 'desired' parameter, and have the correct data filled
into the 'obtained' parameter, possibly allowing or not allowing format changes.

So... 'obtained' becomes the audio format the user callback is expected to use,
and we add flags to allow the application to specify which format changes are
allowed.

Note: We really need to add a way to query the 'obtained' audio spec.
include/SDL_audio.h
src/audio/SDL_audio.c
     1.1 --- a/include/SDL_audio.h	Sat Dec 13 06:27:58 2008 +0000
     1.2 +++ b/include/SDL_audio.h	Sat Dec 13 06:36:47 2008 +0000
     1.3 @@ -129,6 +129,11 @@
     1.4  #define AUDIO_F32SYS	AUDIO_F32MSB
     1.5  #endif
     1.6  
     1.7 +/* Which audio format changes are allowed when opening a device */
     1.8 +#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE    0x00000001
     1.9 +#define SDL_AUDIO_ALLOW_FORMAT_CHANGE       0x00000002
    1.10 +#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE     0x00000004
    1.11 +#define SDL_AUDIO_ALLOW_ANY_CHANGE          (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE)
    1.12  
    1.13  /* A structure to hold a set of audio conversion filters and buffers */
    1.14  struct SDL_AudioCVT;
    1.15 @@ -217,7 +222,7 @@
    1.16   * may modify the requested size of the audio buffer, you should allocate
    1.17   * any local mixing buffers after you open the audio device.
    1.18   */
    1.19 -extern DECLSPEC int SDLCALL SDL_OpenAudio(const SDL_AudioSpec * desired,
    1.20 +extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,
    1.21                                            SDL_AudioSpec * obtained);
    1.22  
    1.23  /*
    1.24 @@ -277,7 +282,9 @@
    1.25                                                                SDL_AudioSpec *
    1.26                                                                desired,
    1.27                                                                SDL_AudioSpec *
    1.28 -                                                              obtained);
    1.29 +                                                              obtained,
    1.30 +                                                              int
    1.31 +                                                              allowed_changes);
    1.32  
    1.33  
    1.34  
     2.1 --- a/src/audio/SDL_audio.c	Sat Dec 13 06:27:58 2008 +0000
     2.2 +++ b/src/audio/SDL_audio.c	Sat Dec 13 06:36:47 2008 +0000
     2.3 @@ -792,12 +792,13 @@
     2.4  
     2.5  static SDL_AudioDeviceID
     2.6  open_audio_device(const char *devname, int iscapture,
     2.7 -                  const SDL_AudioSpec * _desired, SDL_AudioSpec * obtained,
     2.8 -                  int min_id)
     2.9 +                  const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
    2.10 +                  int allowed_changes, int min_id)
    2.11  {
    2.12      SDL_AudioDeviceID id = 0;
    2.13 -    SDL_AudioSpec desired;
    2.14 +    SDL_AudioSpec _obtained;
    2.15      SDL_AudioDevice *device;
    2.16 +    SDL_bool build_cvt;
    2.17      int i = 0;
    2.18  
    2.19      if (!SDL_WasInit(SDL_INIT_AUDIO)) {
    2.20 @@ -810,7 +811,10 @@
    2.21          return 0;
    2.22      }
    2.23  
    2.24 -    if (!prepare_audiospec(_desired, &desired)) {
    2.25 +    if (!obtained) {
    2.26 +        obtained = &_obtained;
    2.27 +    }
    2.28 +    if (!prepare_audiospec(desired, obtained)) {
    2.29          return 0;
    2.30      }
    2.31  
    2.32 @@ -865,7 +869,7 @@
    2.33          return 0;
    2.34      }
    2.35      SDL_memset(device, '\0', sizeof(SDL_AudioDevice));
    2.36 -    SDL_memcpy(&device->spec, &desired, sizeof(SDL_AudioSpec));
    2.37 +    device->spec = *obtained;
    2.38      device->enabled = 1;
    2.39      device->paused = 1;
    2.40      device->iscapture = iscapture;
    2.41 @@ -886,12 +890,6 @@
    2.42      }
    2.43      device->opened = 1;
    2.44  
    2.45 -    /* If the audio driver changes the buffer size, accept it */
    2.46 -    if (device->spec.samples != desired.samples) {
    2.47 -        desired.samples = device->spec.samples;
    2.48 -        SDL_CalculateAudioSpec(&device->spec);
    2.49 -    }
    2.50 -
    2.51      /* Allocate a fake audio memory buffer */
    2.52      device->fake_stream = SDL_AllocAudioMem(device->spec.size);
    2.53      if (device->fake_stream == NULL) {
    2.54 @@ -900,23 +898,47 @@
    2.55          return 0;
    2.56      }
    2.57  
    2.58 +    /* If the audio driver changes the buffer size, accept it */
    2.59 +    if (device->spec.samples != obtained->samples) {
    2.60 +        obtained->samples = device->spec.samples;
    2.61 +        SDL_CalculateAudioSpec(obtained);
    2.62 +    }
    2.63 +
    2.64      /* See if we need to do any conversion */
    2.65 -    if (obtained != NULL) {
    2.66 -        SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec));
    2.67 -    } else if (desired.freq != device->spec.freq ||
    2.68 -               desired.format != device->spec.format ||
    2.69 -               desired.channels != device->spec.channels) {
    2.70 +    build_cvt = SDL_FALSE;
    2.71 +    if (obtained->freq != device->spec.freq) {
    2.72 +        if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
    2.73 +            obtained->freq = device->spec.freq;
    2.74 +        } else {
    2.75 +            build_cvt = SDL_TRUE;
    2.76 +        }
    2.77 +    }
    2.78 +    if (obtained->format != device->spec.format) {
    2.79 +        if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
    2.80 +            obtained->format = device->spec.format;
    2.81 +        } else {
    2.82 +            build_cvt = SDL_TRUE;
    2.83 +        }
    2.84 +    }
    2.85 +    if (obtained->channels != device->spec.channels) {
    2.86 +        if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
    2.87 +            obtained->channels = device->spec.channels;
    2.88 +        } else {
    2.89 +            build_cvt = SDL_TRUE;
    2.90 +        }
    2.91 +    }
    2.92 +    if (build_cvt) {
    2.93          /* Build an audio conversion block */
    2.94          if (SDL_BuildAudioCVT(&device->convert,
    2.95 -                              desired.format, desired.channels,
    2.96 -                              desired.freq,
    2.97 +                              obtained->format, obtained->channels,
    2.98 +                              obtained->freq,
    2.99                                device->spec.format, device->spec.channels,
   2.100                                device->spec.freq) < 0) {
   2.101              close_audio_device(device);
   2.102              return 0;
   2.103          }
   2.104          if (device->convert.needed) {
   2.105 -            device->convert.len = (int) (((double) desired.size) /
   2.106 +            device->convert.len = (int) (((double) obtained->size) /
   2.107                                           device->convert.len_ratio);
   2.108  
   2.109              device->convert.buf =
   2.110 @@ -966,7 +988,7 @@
   2.111  
   2.112  
   2.113  int
   2.114 -SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   2.115 +SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   2.116  {
   2.117      SDL_AudioDeviceID id = 0;
   2.118  
   2.119 @@ -983,7 +1005,12 @@
   2.120          return (-1);
   2.121      }
   2.122  
   2.123 -    id = open_audio_device(NULL, 0, desired, obtained, 1);
   2.124 +    if (obtained) {
   2.125 +        id = open_audio_device(NULL, 0, desired, obtained,
   2.126 +                               SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
   2.127 +    } else {
   2.128 +        id = open_audio_device(NULL, 0, desired, desired, 0, 1);
   2.129 +    }
   2.130      if (id > 1) {               /* this should never happen in theory... */
   2.131          SDL_CloseAudioDevice(id);
   2.132          SDL_SetError("Internal error"); /* MUST be Device ID #1! */
   2.133 @@ -995,9 +1022,11 @@
   2.134  
   2.135  SDL_AudioDeviceID
   2.136  SDL_OpenAudioDevice(const char *device, int iscapture,
   2.137 -                    const SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   2.138 +                    const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
   2.139 +                    int allowed_changes)
   2.140  {
   2.141 -    return open_audio_device(device, iscapture, desired, obtained, 2);
   2.142 +    return open_audio_device(device, iscapture, desired, obtained,
   2.143 +                             allowed_changes, 2);
   2.144  }
   2.145  
   2.146  SDL_audiostatus