SDL: audio: Remove AUDIO_U16* support.

From f48d0cc164c02c20a00ff2b0b4a57f54c905b6d6 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Tue, 28 Feb 2023 15:17:47 -0500
Subject: [PATCH] audio: Remove AUDIO_U16* support.

It wasn't heavily used, and you can't use memset to silence a U16 buffer.

Fixes #7380.
---
 docs/README-migration.md            |  20 ++
 include/SDL3/SDL_audio.h            |   5 -
 src/audio/SDL_audio.c               |  52 ++---
 src/audio/SDL_audio_c.h             |   2 -
 src/audio/SDL_audiocvt.c            |   8 -
 src/audio/SDL_audiotypecvt.c        | 281 ----------------------------
 src/audio/SDL_mixer.c               |  51 -----
 src/audio/alsa/SDL_alsa_audio.c     |   6 -
 src/audio/coreaudio/SDL_coreaudio.m |   2 +-
 src/audio/dsp/SDL_dspaudio.c        |  10 -
 src/audio/netbsd/SDL_netbsdaudio.c  |   6 -
 src/audio/pipewire/SDL_pipewire.c   |   6 -
 src/audio/sndio/SDL_sndioaudio.c    |   4 -
 src/test/SDL_test_common.c          |  18 +-
 test/testautomation_audio.c         |   8 +-
 15 files changed, 41 insertions(+), 438 deletions(-)

diff --git a/docs/README-migration.md b/docs/README-migration.md
index ca05e38841ce..8a6c0416bbf2 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -78,6 +78,26 @@ should be changed to:
     SDL_free(dst_data);

+AUDIO_U16, AUDIO_U16LSB, AUDIO_U16MSB, and AUDIO_U16SYS have been removed. They were not heavily used, and one could not memset a buffer in this format to silence with a single byte value. Use a different audio format.
+
+If you need to convert U16 audio data to a still-supported format at runtime, the fastest, lossless conversion is to AUDIO_S16:
+
+```c

  • /* this converts the buffer in-place. The buffer size does not change. */
  • Sint16 *audio_ui16_to_si16(Uint16 *buffer, const size_t num_samples)
  • {
  •    size_t i;
    
  •    const Uint16 *src = buffer;
    
  •    Sint16 *dst = (Sint16 *) buffer;
    
  •    for (i = 0; i < num_samples; i++) {
    
  •        dst[i] = (Sint16) (src[i] ^ 0x8000);
    
  •    }
    
  •    return dst;
    
  • }
    +```

The following functions have been renamed:

  • SDL_AudioStreamAvailable() => SDL_GetAudioStreamAvailable()
    diff --git a/include/SDL3/SDL_audio.h b/include/SDL3/SDL_audio.h
    index ce8529a95939…bcac63d1ef1c 100644
    — a/include/SDL3/SDL_audio.h
    +++ b/include/SDL3/SDL_audio.h
    @@ -90,11 +90,8 @@ typedef Uint16 SDL_AudioFormat;
    /* @{ */
    #define AUDIO_U8 0x0008 /< Unsigned 8-bit samples */
    #define AUDIO_S8 0x8008 /
    < Signed 8-bit samples */
    -#define AUDIO_U16LSB 0x0010 /< Unsigned 16-bit samples */
    #define AUDIO_S16LSB 0x8010 /
    < Signed 16-bit samples */
    -#define AUDIO_U16MSB 0x1010 /< As above, but big-endian byte order */
    #define AUDIO_S16MSB 0x9010 /
    < As above, but big-endian byte order /
    -#define AUDIO_U16 AUDIO_U16LSB
    #define AUDIO_S16 AUDIO_S16LSB
    /
    @} */

@@ -121,12 +118,10 @@ typedef Uint16 SDL_AudioFormat;
/
/
@{ */
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
-#define AUDIO_U16SYS AUDIO_U16LSB
#define AUDIO_S16SYS AUDIO_S16LSB
#define AUDIO_S32SYS AUDIO_S32LSB
#define AUDIO_F32SYS AUDIO_F32LSB
#else
-#define AUDIO_U16SYS AUDIO_U16MSB
#define AUDIO_S16SYS AUDIO_S16MSB
#define AUDIO_S32SYS AUDIO_S32MSB
#define AUDIO_F32SYS AUDIO_F32MSB
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index 23ee40053bcf…8caa26b762a6 100644
— a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -847,13 +847,8 @@ static SDL_AudioFormat SDL_ParseAudioFormat(const char *string)
return AUDIO_##x
CHECK_FMT_STRING(U8);
CHECK_FMT_STRING(S8);

  • CHECK_FMT_STRING(U16LSB);
    CHECK_FMT_STRING(S16LSB);
  • CHECK_FMT_STRING(U16MSB);
    CHECK_FMT_STRING(S16MSB);
  • CHECK_FMT_STRING(U16SYS);
  • CHECK_FMT_STRING(S16SYS);
  • CHECK_FMT_STRING(U16);
    CHECK_FMT_STRING(S16);
    CHECK_FMT_STRING(S32LSB);
    CHECK_FMT_STRING(S32MSB);
    @@ -1600,30 +1595,18 @@ void SDL_QuitAudio(void)
    #endif
    }

-#define NUM_FORMATS 10
-static int format_idx;
+#define NUM_FORMATS 8
+static int format_idx; /* !!! FIXME: whoa, why are there globals in use here?! */
static int format_idx_sub;
static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {

  • { AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  •  AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB },
    
  • { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  •  AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB },
    
  • { AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
  •  AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8 },
    
  • { AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
  •  AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8 },
    
  • { AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
  •  AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8 },
    
  • { AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
  •  AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8 },
    
  • { AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
  •  AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8 },
    
  • { AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
  •  AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8 },
    
  • { AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
  •  AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8 },
    
  • { AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
  •  AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8 },
    
  • { AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB },
  • { AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB },
  • { AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8 },
  • { AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8 },
  • { AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8, AUDIO_S8 },
  • { AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8, AUDIO_S8 },
  • { AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U8, AUDIO_S8 },
  • { AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U8, AUDIO_S8 },
    };

SDL_AudioFormat
@@ -1649,20 +1632,7 @@ SDL_GetNextAudioFormat(void)

Uint8 SDL_GetSilenceValueForFormat(const SDL_AudioFormat format)
{

  • switch (format) {
  • /* !!! FIXME: 0x80 isn’t perfect for U16, but we can’t fit 0x8000 in a
  •   !!! FIXME:  byte for SDL_memset() use. This is actually 0.1953 percent
    
  •   !!! FIXME:  off from silence. Maybe just don't use U16. */
    
  • case AUDIO_U16LSB:
  • case AUDIO_U16MSB:
  • case AUDIO_U8:
  •    return 0x80;
    
  • default:
  •    break;
    
  • }
  • return 0x00;
  • return (format == AUDIO_U8) ? 0x80 : 0x00;
    }

void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
diff --git a/src/audio/SDL_audio_c.h b/src/audio/SDL_audio_c.h
index b1d585011635…97bef2adea63 100644
— a/src/audio/SDL_audio_c.h
+++ b/src/audio/SDL_audio_c.h
@@ -66,12 +66,10 @@ typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt, SDL_AudioFo
extern SDL_AudioFilter SDL_Convert_S8_to_F32;
extern SDL_AudioFilter SDL_Convert_U8_to_F32;
extern SDL_AudioFilter SDL_Convert_S16_to_F32;
-extern SDL_AudioFilter SDL_Convert_U16_to_F32;
extern SDL_AudioFilter SDL_Convert_S32_to_F32;
extern SDL_AudioFilter SDL_Convert_F32_to_S8;
extern SDL_AudioFilter SDL_Convert_F32_to_U8;
extern SDL_AudioFilter SDL_Convert_F32_to_S16;
-extern SDL_AudioFilter SDL_Convert_F32_to_U16;
extern SDL_AudioFilter SDL_Convert_F32_to_S32;

/**
diff --git a/src/audio/SDL_audiocvt.c b/src/audio/SDL_audiocvt.c
index e6c1a8684fca…ab19b31207c0 100644
— a/src/audio/SDL_audiocvt.c
+++ b/src/audio/SDL_audiocvt.c
@@ -441,9 +441,6 @@ static int SDL_BuildAudioTypeCVTToFloat(SDL_AudioCVT *cvt, const SDL_AudioFormat
case AUDIO_S16:
filter = SDL_Convert_S16_to_F32;
break;

  •    case AUDIO_U16:
    
  •        filter = SDL_Convert_U16_to_F32;
    
  •        break;
       case AUDIO_S32:
           filter = SDL_Convert_S32_to_F32;
           break;
    

@@ -492,9 +489,6 @@ static int SDL_BuildAudioTypeCVTFromFloat(SDL_AudioCVT *cvt, const SDL_AudioForm
case AUDIO_S16:
filter = SDL_Convert_F32_to_S16;
break;

  •    case AUDIO_U16:
    
  •        filter = SDL_Convert_F32_to_U16;
    
  •        break;
       case AUDIO_S32:
           filter = SDL_Convert_F32_to_S32;
           break;
    

@@ -735,9 +729,7 @@ static SDL_bool SDL_IsSupportedAudioFormat(const SDL_AudioFormat fmt)
switch (fmt) {
case AUDIO_U8:
case AUDIO_S8:

  • case AUDIO_U16LSB:
    case AUDIO_S16LSB:
  • case AUDIO_U16MSB:
    case AUDIO_S16MSB:
    case AUDIO_S32LSB:
    case AUDIO_S32MSB:
    diff --git a/src/audio/SDL_audiotypecvt.c b/src/audio/SDL_audiotypecvt.c
    index a82243ab15ff…6a99038fc60c 100644
    — a/src/audio/SDL_audiotypecvt.c
    +++ b/src/audio/SDL_audiotypecvt.c
    @@ -50,12 +50,10 @@
    SDL_AudioFilter SDL_Convert_S8_to_F32 = NULL;
    SDL_AudioFilter SDL_Convert_U8_to_F32 = NULL;
    SDL_AudioFilter SDL_Convert_S16_to_F32 = NULL;
    -SDL_AudioFilter SDL_Convert_U16_to_F32 = NULL;
    SDL_AudioFilter SDL_Convert_S32_to_F32 = NULL;
    SDL_AudioFilter SDL_Convert_F32_to_S8 = NULL;
    SDL_AudioFilter SDL_Convert_F32_to_U8 = NULL;
    SDL_AudioFilter SDL_Convert_F32_to_S16 = NULL;
    -SDL_AudioFilter SDL_Convert_F32_to_U16 = NULL;
    SDL_AudioFilter SDL_Convert_F32_to_S32 = NULL;

#define DIVBY128 0.0078125f
@@ -117,24 +115,6 @@ static void SDLCALL SDL_Convert_S16_to_F32_Scalar(SDL_AudioCVT *cvt, SDL_AudioFo
}
}

-static void SDLCALL SDL_Convert_U16_to_F32_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
-{

  • const Uint16 *src = ((const Uint16 *)(cvt->buf + cvt->len_cvt)) - 1;
  • float *dst = ((float *)(cvt->buf + cvt->len_cvt * 2)) - 1;
  • int i;
  • LOG_DEBUG_CONVERT(“AUDIO_U16”, “AUDIO_F32”);
  • for (i = cvt->len_cvt / sizeof(Uint16); i; --i, --src, --dst) {
  •    *dst = (((float)*src) * DIVBY32768) - 1.0f;
    
  • }
  • cvt->len_cvt *= 2;
  • if (cvt->filters[++cvt->filter_index]) {
  •    cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
    
  • }
    -}

static void SDLCALL SDL_Convert_S32_to_F32_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
const Sint32 *src = (const Sint32 *)cvt->buf;
@@ -227,31 +207,6 @@ static void SDLCALL SDL_Convert_F32_to_S16_Scalar(SDL_AudioCVT *cvt, SDL_AudioFo
}
}

-static void SDLCALL SDL_Convert_F32_to_U16_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
-{

  • const float *src = (const float *)cvt->buf;
  • Uint16 *dst = (Uint16 *)cvt->buf;
  • int i;
  • LOG_DEBUG_CONVERT(“AUDIO_F32”, “AUDIO_U16”);
  • for (i = cvt->len_cvt / sizeof(float); i; --i, ++src, ++dst) {
  •    const float sample = *src;
    
  •    if (sample >= 1.0f) {
    
  •        *dst = 65535;
    
  •    } else if (sample <= -1.0f) {
    
  •        *dst = 0;
    
  •    } else {
    
  •        *dst = (Uint16)((sample + 1.0f) * 32767.0f);
    
  •    }
    
  • }
  • cvt->len_cvt /= 2;
  • if (cvt->filters[++cvt->filter_index]) {
  •    cvt->filters[cvt->filter_index](cvt, AUDIO_U16SYS);
    
  • }
    -}

static void SDLCALL SDL_Convert_F32_to_S32_Scalar(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
const float *src = (const float *)cvt->buf;
@@ -461,60 +416,6 @@ static void SDLCALL SDL_Convert_S16_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioForm
}
}

-static void SDLCALL SDL_Convert_U16_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
-{

  • const Uint16 *src = ((const Uint16 *)(cvt->buf + cvt->len_cvt)) - 1;
  • float *dst = ((float *)(cvt->buf + cvt->len_cvt * 2)) - 1;
  • int i;
  • LOG_DEBUG_CONVERT(“AUDIO_U16”, “AUDIO_F32 (using SSE2)”);
  • /* Get dst aligned to 16 bytes (since buffer is growing, we don’t have to worry about overreading from src) */
  • for (i = cvt->len_cvt / sizeof(Sint16); i && (((size_t)(dst - 7)) & 15); --i, --src, --dst) {
  •    *dst = (((float)*src) * DIVBY32768) - 1.0f;
    
  • }
  • src -= 7;
  • dst -= 7; /* adjust to read SSE blocks from the start. */
  • SDL_assert(!i || !(((size_t)dst) & 15));
  • /* Make sure src is aligned too. */
  • if (!(((size_t)src) & 15)) {
  •    /* Aligned! Do SSE blocks as long as we have 16 bytes available. */
    
  •    const __m128 divby32768 = _mm_set1_ps(DIVBY32768);
    
  •    const __m128 minus1 = _mm_set1_ps(-1.0f);
    
  •    while (i >= 8) {                                               /* 8 * 16-bit */
    
  •        const __m128i ints = _mm_load_si128((__m128i const *)src); /* get 8 sint16 into an XMM register. */
    
  •        /* treat as int32, shift left to clear every other sint16, then back right with zero-extend. Now sint32. */
    
  •        const __m128i a = _mm_srli_epi32(_mm_slli_epi32(ints, 16), 16);
    
  •        /* right-shift-sign-extend gets us sint32 with the other set of values. */
    
  •        const __m128i b = _mm_srli_epi32(ints, 16);
    
  •        /* Interleave these back into the right order, convert to float, multiply, store. */
    
  •        _mm_store_ps(dst, _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi32(a, b)), divby32768), minus1));
    
  •        _mm_store_ps(dst + 4, _mm_add_ps(_mm_mul_ps(_mm_cvtepi32_ps(_mm_unpackhi_epi32(a, b)), divby32768), minus1));
    
  •        i -= 8;
    
  •        src -= 8;
    
  •        dst -= 8;
    
  •    }
    
  • }
  • src += 7;
  • dst += 7; /* adjust for any scalar finishing. */
  • /* Finish off any leftovers with scalar operations. */
  • while (i) {
  •    *dst = (((float)*src) * DIVBY32768) - 1.0f;
    
  •    i--;
    
  •    src--;
    
  •    dst--;
    
  • }
  • cvt->len_cvt *= 2;
  • if (cvt->filters[++cvt->filter_index]) {
  •    cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
    
  • }
    -}

static void SDLCALL SDL_Convert_S32_to_F32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
const Sint32 *src = (const Sint32 *)cvt->buf;
@@ -745,75 +646,6 @@ static void SDLCALL SDL_Convert_F32_to_S16_SSE2(SDL_AudioCVT *cvt, SDL_AudioForm
}
}

-static void SDLCALL SDL_Convert_F32_to_U16_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
-{

  • const float *src = (const float *)cvt->buf;
  • Uint16 *dst = (Uint16 *)cvt->buf;
  • int i;
  • LOG_DEBUG_CONVERT(“AUDIO_F32”, “AUDIO_U16 (using SSE2)”);
  • /* Get dst aligned to 16 bytes */
  • for (i = cvt->len_cvt / sizeof(float); i && (((size_t)dst) & 15); --i, ++src, ++dst) {
  •    const float sample = *src;
    
  •    if (sample >= 1.0f) {
    
  •        *dst = 65535;
    
  •    } else if (sample <= -1.0f) {
    
  •        *dst = 0;
    
  •    } else {
    
  •        *dst = (Uint16)((sample + 1.0f) * 32767.0f);
    
  •    }
    
  • }
  • SDL_assert(!i || !(((size_t)dst) & 15));
  • /* Make sure src is aligned too. */
  • if (!(((size_t)src) & 15)) {
  •    /* Aligned! Do SSE blocks as long as we have 16 bytes available. */
    
  •    /* This calculates differently than the scalar path because SSE2 can't
    
  •       pack int32 data down to unsigned int16. _mm_packs_epi32 does signed
    
  •       saturation, so that would corrupt our data. _mm_packus_epi32 exists,
    
  •       but not before SSE 4.1. So we convert from float to sint16, packing
    
  •       that down with legit signed saturation, and then xor the top bit
    
  •       against 1. This results in the correct unsigned 16-bit value, even
    
  •       though it looks like dark magic. */
    
  •    const __m128 mulby32767 = _mm_set1_ps(32767.0f);
    
  •    const __m128i topbit = _mm_set1_epi16(-32768);
    
  •    const __m128 one = _mm_set1_ps(1.0f);
    
  •    const __m128 negone = _mm_set1_ps(-1.0f);
    
  •    __m128i *mmdst = (__m128i *)dst;
    
  •    while (i >= 8) {                                                                                                              /* 8 * float32 */
    
  •        const __m128i ints1 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src)), one), mulby32767));     /* load 4 floats, clamp, convert to sint32 */
    
  •        const __m128i ints2 = _mm_cvtps_epi32(_mm_mul_ps(_mm_min_ps(_mm_max_ps(negone, _mm_load_ps(src + 4)), one), mulby32767)); /* load 4 floats, clamp, convert to sint32 */
    
  •        _mm_store_si128(mmdst, _mm_xor_si128(_mm_packs_epi32(ints1, ints2), topbit));                                             /* pack to sint16, xor top bit, store out. */
    
  •        i -= 8;
    
  •        src += 8;
    
  •        mmdst++;
    
  •    }
    
  •    dst = (Uint16 *)mmdst;
    
  • }
  • /* Finish off any leftovers with scalar operations. */
  • while (i) {
  •    const float sample = *src;
    
  •    if (sample >= 1.0f) {
    
  •        *dst = 65535;
    
  •    } else if (sample <= -1.0f) {
    
  •        *dst = 0;
    
  •    } else {
    
  •        *dst = (Uint16)((sample + 1.0f) * 32767.0f);
    
  •    }
    
  •    i--;
    
  •    src++;
    
  •    dst++;
    
  • }
  • cvt->len_cvt /= 2;
  • if (cvt->filters[++cvt->filter_index]) {
  •    cvt->filters[cvt->filter_index](cvt, AUDIO_U16SYS);
    
  • }
    -}

static void SDLCALL SDL_Convert_F32_to_S32_SSE2(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
const float *src = (const float *)cvt->buf;
@@ -1036,56 +868,6 @@ static void SDLCALL SDL_Convert_S16_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioForm
}
}

-static void SDLCALL SDL_Convert_U16_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
-{

  • const Uint16 *src = ((const Uint16 *)(cvt->buf + cvt->len_cvt)) - 1;
  • float *dst = ((float *)(cvt->buf + cvt->len_cvt * 2)) - 1;
  • int i;
  • LOG_DEBUG_CONVERT(“AUDIO_U16”, “AUDIO_F32 (using NEON)”);
  • /* Get dst aligned to 16 bytes (since buffer is growing, we don’t have to worry about overreading from src) */
  • for (i = cvt->len_cvt / sizeof(Sint16); i && (((size_t)(dst - 7)) & 15); --i, --src, --dst) {
  •    *dst = (((float)*src) * DIVBY32768) - 1.0f;
    
  • }
  • src -= 7;
  • dst -= 7; /* adjust to read NEON blocks from the start. */
  • SDL_assert(!i || !(((size_t)dst) & 15));
  • /* Make sure src is aligned too. */
  • if (!(((size_t)src) & 15)) {
  •    /* Aligned! Do NEON blocks as long as we have 16 bytes available. */
    
  •    const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768);
    
  •    const float32x4_t negone = vdupq_n_f32(-1.0f);
    
  •    while (i >= 8) {                                               /* 8 * 16-bit */
    
  •        const uint16x8_t uints = vld1q_u16((uint16_t const *)src); /* get 8 uint16 into a NEON register. */
    
  •        /* split uint16 to two int32, then convert to float, then multiply to normalize, subtract for sign, store. */
    
  •        vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uints))), divby32768));
    
  •        vst1q_f32(dst + 4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uints))), divby32768));
    
  •        i -= 8;
    
  •        src -= 8;
    
  •        dst -= 8;
    
  •    }
    
  • }
  • src += 7;
  • dst += 7; /* adjust for any scalar finishing. */
  • /* Finish off any leftovers with scalar operations. */
  • while (i) {
  •    *dst = (((float)*src) * DIVBY32768) - 1.0f;
    
  •    i--;
    
  •    src--;
    
  •    dst--;
    
  • }
  • cvt->len_cvt *= 2;
  • if (cvt->filters[++cvt->filter_index]) {
  •    cvt->filters[cvt->filter_index](cvt, AUDIO_F32SYS);
    
  • }
    -}

static void SDLCALL SDL_Convert_S32_to_F32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
const Sint32 *src = (const Sint32 *)cvt->buf;
@@ -1321,67 +1103,6 @@ static void SDLCALL SDL_Convert_F32_to_S16_NEON(SDL_AudioCVT *cvt, SDL_AudioForm
}
}

-static void SDLCALL SDL_Convert_F32_to_U16_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
-{

  • const float *src = (const float *)cvt->buf;
  • Uint16 *dst = (Uint16 *)cvt->buf;
  • int i;
  • LOG_DEBUG_CONVERT(“AUDIO_F32”, “AUDIO_U16 (using NEON)”);
  • /* Get dst aligned to 16 bytes */
  • for (i = cvt->len_cvt / sizeof(float); i && (((size_t)dst) & 15); --i, ++src, ++dst) {
  •    const float sample = *src;
    
  •    if (sample >= 1.0f) {
    
  •        *dst = 65535;
    
  •    } else if (sample <= -1.0f) {
    
  •        *dst = 0;
    
  •    } else {
    
  •        *dst = (Uint16)((sample + 1.0f) * 32767.0f);
    
  •    }
    
  • }
  • SDL_assert(!i || !(((size_t)dst) & 15));
  • /* Make sure src is aligned too. */
  • if (!(((size_t)src) & 15)) {
  •    /* Aligned! Do NEON blocks as long as we have 16 bytes available. */
    
  •    const float32x4_t one = vdupq_n_f32(1.0f);
    
  •    const float32x4_t negone = vdupq_n_f32(-1.0f);
    
  •    const float32x4_t mulby32767 = vdupq_n_f32(32767.0f);
    
  •    uint16_t *mmdst = (uint16_t *)dst;
    
  •    while (i >= 8) {                                                                                                                           /* 8 * float32 */
    
  •        const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby32767));     /* load 4 floats, clamp, convert to uint32 */
    
  •        const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), one), mulby32767)); /* load 4 floats, clamp, convert to uint32 */
    
  •        vst1q_u16(mmdst, vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2)));                                                                  /* narrow to uint16, combine, store out. */
    
  •        i -= 8;
    
  •        src += 8;
    
  •        mmdst += 8;
    
  •    }
    
  •    dst = (Uint16 *)mmdst;
    
  • }
  • /* Finish off any leftovers with scalar operations. */
  • while (i) {
  •    const float sample = *src;
    
  •    if (sample >= 1.0f) {
    
  •        *dst = 65535;
    
  •    } else if (sample <= -1.0f) {
    
  •        *dst = 0;
    
  •    } else {
    
  •        *dst = (Uint16)((sample + 1.0f) * 32767.0f);
    
  •    }
    
  •    i--;
    
  •    src++;
    
  •    dst++;
    
  • }
  • cvt->len_cvt /= 2;
  • if (cvt->filters[++cvt->filter_index]) {
  •    cvt->filters[cvt->filter_index](cvt, AUDIO_U16SYS);
    
  • }
    -}

static void SDLCALL SDL_Convert_F32_to_S32_NEON(SDL_AudioCVT *cvt, SDL_AudioFormat format)
{
const float *src = (const float *)cvt->buf;
@@ -1453,12 +1174,10 @@ void SDL_ChooseAudioConverters(void)
SDL_Convert_S8_to_F32 = SDL_Convert_S8_to_F32_##fntype;
SDL_Convert_U8_to_F32 = SDL_Convert_U8_to_F32_##fntype;
SDL_Convert_S16_to_F32 = SDL_Convert_S16_to_F32_##fntype; \

  • SDL_Convert_U16_to_F32 = SDL_Convert_U16_to_F32_##fntype;
    SDL_Convert_S32_to_F32 = SDL_Convert_S32_to_F32_##fntype;
    SDL_Convert_F32_to_S8 = SDL_Convert_F32_to_S8_##fntype;
    SDL_Convert_F32_to_U8 = SDL_Convert_F32_to_U8_##fntype;
    SDL_Convert_F32_to_S16 = SDL_Convert_F32_to_S16_##fntype; \
  • SDL_Convert_F32_to_U16 = SDL_Convert_F32_to_U16_##fntype;
    SDL_Convert_F32_to_S32 = SDL_Convert_F32_to_S32_##fntype;
    converters_chosen = SDL_TRUE

diff --git a/src/audio/SDL_mixer.c b/src/audio/SDL_mixer.c
index 0804e000c636…337083cac7b6 100644
— a/src/audio/SDL_mixer.c
+++ b/src/audio/SDL_mixer.c
@@ -80,7 +80,6 @@ static const Uint8 mix8[] = {
/* The volume ranges from 0 - 128 */
#define ADJUST_VOLUME(s, v) ((s) = ((s) * (v)) / SDL_MIX_MAXVOLUME)
#define ADJUST_VOLUME_U8(s, v) ((s) = ((((s) - 128) * (v)) / SDL_MIX_MAXVOLUME) + 128)
-#define ADJUST_VOLUME_U16(s, v) ((s) = ((((s) - 32768) * (v)) / SDL_MIX_MAXVOLUME) + 32768)

int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format,
Uint32 len, int volume)
@@ -177,56 +176,6 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format,
}
} break;

  • case AUDIO_U16LSB:
  • {
  •    Uint16 src1, src2;
    
  •    int dst_sample;
    
  •    const int max_audioval = SDL_MAX_SINT16;
    
  •    const int min_audioval = SDL_MIN_SINT16;
    
  •    len /= 2;
    
  •    while (len--) {
    
  •        src1 = SDL_SwapLE16(*(Uint16 *)src);
    
  •        ADJUST_VOLUME_U16(src1, volume);
    
  •        src2 = SDL_SwapLE16(*(Uint16 *)dst);
    
  •        src += 2;
    
  •        dst_sample = src1 + src2 - 32768 * 2;
    
  •        if (dst_sample > max_audioval) {
    
  •            dst_sample = max_audioval;
    
  •        } else if (dst_sample < min_audioval) {
    
  •            dst_sample = min_audioval;
    
  •        }
    
  •        dst_sample += 32768;
    
  •        *(Uint16 *)dst = SDL_SwapLE16(dst_sample);
    
  •        dst += 2;
    
  •    }
    
  • } break;
  • case AUDIO_U16MSB:
  • {
  •    Uint16 src1, src2;
    
  •    int dst_sample;
    
  •    const int max_audioval = SDL_MAX_SINT16;
    
  •    const int min_audioval = SDL_MIN_SINT16;
    
  •    len /= 2;
    
  •    while (len--) {
    
  •        src1 = SDL_SwapBE16(*(Uint16 *)src);
    
  •        ADJUST_VOLUME_U16(src1, volume);
    
  •        src2 = SDL_SwapBE16(*(Uint16 *)dst);
    
  •        src += 2;
    
  •        dst_sample = src1 + src2 - 32768 * 2;
    
  •        if (dst_sample > max_audioval) {
    
  •            dst_sample = max_audioval;
    
  •        } else if (dst_sample < min_audioval) {
    
  •            dst_sample = min_audioval;
    
  •        }
    
  •        dst_sample += 32768;
    
  •        *(Uint16 *)dst = SDL_SwapBE16(dst_sample);
    
  •        dst += 2;
    
  •    }
    
  • } break;
  • case AUDIO_S32LSB:
    {
    const Uint32 *src32 = (Uint32 *)src;
    diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c
    index 02f05651f24b…e25538cd42b9 100644
    — a/src/audio/alsa/SDL_alsa_audio.c
    +++ b/src/audio/alsa/SDL_alsa_audio.c
    @@ -584,12 +584,6 @@ static int ALSA_OpenDevice(_THIS, const char *devname)
    case AUDIO_S16MSB:
    format = SND_PCM_FORMAT_S16_BE;
    break;
  •    case AUDIO_U16LSB:
    
  •        format = SND_PCM_FORMAT_U16_LE;
    
  •        break;
    
  •    case AUDIO_U16MSB:
    
  •        format = SND_PCM_FORMAT_U16_BE;
    
  •        break;
       case AUDIO_S32LSB:
           format = SND_PCM_FORMAT_S32_LE;
           break;
    

diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m
index c70a595f09e3…c089a267aec1 100644
— a/src/audio/coreaudio/SDL_coreaudio.m
+++ b/src/audio/coreaudio/SDL_coreaudio.m
@@ -1067,7 +1067,7 @@ static int COREAUDIO_OpenDevice(_THIS, const char *devname)
strdesc->mFramesPerPacket = 1;

 for (test_format = SDL_GetFirstAudioFormat(this->spec.format); test_format; test_format = SDL_GetNextAudioFormat()) {
  •    /* CoreAudio handles most of SDL's formats natively, but not U16, apparently. */
    
  •    /* CoreAudio handles most of SDL's formats natively. */
       switch (test_format) {
       case AUDIO_U8:
       case AUDIO_S8:
    

diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c
index 8a7b9d9d1ed2…b2aac5b3962a 100644
— a/src/audio/dsp/SDL_dspaudio.c
+++ b/src/audio/dsp/SDL_dspaudio.c
@@ -145,16 +145,6 @@ static int DSP_OpenDevice(_THIS, const char *devname)
format = AFMT_S8;
}
break;

  •    case AUDIO_U16LSB:
    
  •        if (value & AFMT_U16_LE) {
    
  •            format = AFMT_U16_LE;
    
  •        }
    
  •        break;
    
  •    case AUDIO_U16MSB:
    
  •        if (value & AFMT_U16_BE) {
    
  •            format = AFMT_U16_BE;
    
  •        }
    
  •        break;
    

#endif
default:
format = 0;
diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c
index 464bbf47ebb7…0190d47576b9 100644
— a/src/audio/netbsd/SDL_netbsdaudio.c
+++ b/src/audio/netbsd/SDL_netbsdaudio.c
@@ -250,12 +250,6 @@ static int NETBSDAUDIO_OpenDevice(_THIS, const char *devname)
case AUDIO_S16MSB:
encoding = AUDIO_ENCODING_SLINEAR_BE;
break;

  •    case AUDIO_U16LSB:
    
  •        encoding = AUDIO_ENCODING_ULINEAR_LE;
    
  •        break;
    
  •    case AUDIO_U16MSB:
    
  •        encoding = AUDIO_ENCODING_ULINEAR_BE;
    
  •        break;
       case AUDIO_S32LSB:
           encoding = AUDIO_ENCODING_SLINEAR_LE;
           break;
    

diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c
index 0a05d598a4a0…adc8804ff5ef 100644
— a/src/audio/pipewire/SDL_pipewire.c
+++ b/src/audio/pipewire/SDL_pipewire.c
@@ -915,15 +915,9 @@ static void initialize_spa_info(const SDL_AudioSpec *spec, struct spa_audio_info
case AUDIO_S8:
info->format = SPA_AUDIO_FORMAT_S8;
break;

  • case AUDIO_U16LSB:
  •    info->format = SPA_AUDIO_FORMAT_U16_LE;
    
  •    break;
    
    case AUDIO_S16LSB:
    info->format = SPA_AUDIO_FORMAT_S16_LE;
    break;
  • case AUDIO_U16MSB:
  •    info->format = SPA_AUDIO_FORMAT_U16_BE;
    
  •    break;
    
    case AUDIO_S16MSB:
    info->format = SPA_AUDIO_FORMAT_S16_BE;
    break;
    diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c
    index 544129f2e017…5afc54feeda7 100644
    — a/src/audio/sndio/SDL_sndioaudio.c
    +++ b/src/audio/sndio/SDL_sndioaudio.c
    @@ -291,10 +291,6 @@ static int SNDIO_OpenDevice(_THIS, const char *devname)
    this->spec.format = AUDIO_S16LSB;
    } else if ((par.bps == 2) && (par.sig) && (!par.le)) {
    this->spec.format = AUDIO_S16MSB;
  • } else if ((par.bps == 2) && (!par.sig) && (par.le)) {
  •    this->spec.format = AUDIO_U16LSB;
    
  • } else if ((par.bps == 2) && (!par.sig) && (!par.le)) {
  •    this->spec.format = AUDIO_U16MSB;
    
    } else if ((par.bps == 1) && (par.sig)) {
    this->spec.format = AUDIO_S8;
    } else if ((par.bps == 1) && (!par.sig)) {
    diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c
    index 818efcfbf6e5…2a45a150659f 100644
    — a/src/test/SDL_test_common.c
    +++ b/src/test/SDL_test_common.c
    @@ -39,8 +39,9 @@ static const char *video_usage[] = {
    “[–usable-bounds]”
    };

+/* !!! FIXME: Float32? Sint32? */
static const char *audio_usage[] = {

  • “[–rate N]”, “[–format U8|S8|U16|U16LE|U16BE|S16|S16LE|S16BE]”,
  • “[–rate N]”, “[–format U8|S8|S16|S16LE|S16BE]”,
    “[–channels N]”, “[–samples N]”
    };

@@ -542,18 +543,6 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
state->audiospec.format = AUDIO_S8;
return 2;
}

  •    if (SDL_strcasecmp(argv[index], "U16") == 0) {
    
  •        state->audiospec.format = AUDIO_U16;
    
  •        return 2;
    
  •    }
    
  •    if (SDL_strcasecmp(argv[index], "U16LE") == 0) {
    
  •        state->audiospec.format = AUDIO_U16LSB;
    
  •        return 2;
    
  •    }
    
  •    if (SDL_strcasecmp(argv[index], "U16BE") == 0) {
    
  •        state->audiospec.format = AUDIO_U16MSB;
    
  •        return 2;
    
  •    }
       if (SDL_strcasecmp(argv[index], "S16") == 0) {
           state->audiospec.format = AUDIO_S16;
           return 2;
    

@@ -566,6 +555,9 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
state->audiospec.format = AUDIO_S16MSB;
return 2;
}
+

  •    /* !!! FIXME: Float32? Sint32? */
    
  •    return -1;
    
    }
    if (SDL_strcasecmp(argv[index], “–channels”) == 0) {
    diff --git a/test/testautomation_audio.c b/test/testautomation_audio.c
    index 130dc7f89ef5…2fefb7e7bef9 100644
    — a/test/testautomation_audio.c
    +++ b/test/testautomation_audio.c
    @@ -502,11 +502,11 @@ static int audio_printCurrentAudioDriver(void *arg)

/* Definition of all

(Patch may be truncated, please check the link at the top of this post.)