wave: SDL_LoadWAV now supports 24-bit audio.
authorRyan C. Gordon <icculus@icculus.org>
Thu, 07 Sep 2017 10:56:08 -0400
changeset 114645af6d801e51f
parent 11463 b716f3d736a7
child 11465 9843b1895c45
wave: SDL_LoadWAV now supports 24-bit audio.
src/audio/SDL_wave.c
     1.1 --- a/src/audio/SDL_wave.c	Wed Sep 06 19:35:36 2017 -0400
     1.2 +++ b/src/audio/SDL_wave.c	Thu Sep 07 10:56:08 2017 -0400
     1.3 @@ -403,6 +403,43 @@
     1.4      return (0);
     1.5  }
     1.6  
     1.7 +
     1.8 +static int
     1.9 +ConvertSint24ToSint32(Uint8 ** audio_buf, Uint32 * audio_len)
    1.10 +{
    1.11 +    const double DIVBY8388608 = 0.00000011920928955078125;
    1.12 +    const Uint32 original_len = *audio_len;
    1.13 +    const Uint32 samples = original_len / 3;
    1.14 +    const Uint32 expanded_len = samples * sizeof (Uint32);
    1.15 +    Uint8 *ptr = (Uint8 *) SDL_realloc(*audio_buf, expanded_len);
    1.16 +    const Uint8 *src;
    1.17 +    Uint32 *dst;
    1.18 +    Uint32 i;
    1.19 +
    1.20 +    if (!ptr) {
    1.21 +        return SDL_OutOfMemory();
    1.22 +    }
    1.23 +
    1.24 +    *audio_buf = ptr;
    1.25 +    *audio_len = expanded_len;
    1.26 +
    1.27 +    /* work from end to start, since we're expanding in-place. */
    1.28 +    src = (ptr + original_len) - 3;
    1.29 +    dst = ((Uint32 *) (ptr + expanded_len)) - 1;
    1.30 +    for (i = 0; i < samples; i++) {
    1.31 +        /* There's probably a faster way to do all this. */
    1.32 +        const Sint32 converted = ((Sint32) ( (((Uint32) src[2]) << 24) |
    1.33 +                                             (((Uint32) src[1]) << 16) |
    1.34 +                                             (((Uint32) src[0]) << 8) )) >> 8;
    1.35 +        const double scaled = (((double) converted) * DIVBY8388608);
    1.36 +        src -= 3;
    1.37 +        *(dst--) = (Sint32) (scaled * 2147483647.0);
    1.38 +    }
    1.39 +
    1.40 +    return 0;
    1.41 +}
    1.42 +
    1.43 +
    1.44  /* GUIDs that are used by WAVE_FORMAT_EXTENSIBLE */
    1.45  static const Uint8 extensible_pcm_guid[16] = { 1, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 };
    1.46  static const Uint8 extensible_ieee_guid[16] = { 3, 0, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 };
    1.47 @@ -551,6 +588,9 @@
    1.48          case 16:
    1.49              spec->format = AUDIO_S16;
    1.50              break;
    1.51 +        case 24:  /* convert this. */
    1.52 +            spec->format = AUDIO_S32;
    1.53 +            break;
    1.54          case 32:
    1.55              spec->format = AUDIO_S32;
    1.56              break;
    1.57 @@ -598,6 +638,13 @@
    1.58          }
    1.59      }
    1.60  
    1.61 +    if (SDL_SwapLE16(format->bitspersample) == 24) {
    1.62 +        if (ConvertSint24ToSint32(audio_buf, audio_len) < 0) {
    1.63 +            was_error = 1;
    1.64 +            goto done;
    1.65 +        }
    1.66 +    }
    1.67 +
    1.68      /* Don't return a buffer that isn't a multiple of samplesize */
    1.69      samplesize = ((SDL_AUDIO_BITSIZE(spec->format)) / 8) * spec->channels;
    1.70      *audio_len &= ~(samplesize - 1);