Skip to content

Commit ce11caa

Browse files
committed
alsa: Map 7.1 audio channels to match what Windows and macOS expect.
This matches what we did a long time ago for 5.1 audio. Fixes #55. (FIFTY FIVE. Bug reported 15 years, 3 months, and 11 days ago! lol)
1 parent 9886d89 commit ce11caa

File tree

1 file changed

+54
-14
lines changed

1 file changed

+54
-14
lines changed

src/audio/alsa/SDL_alsa_audio.c

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -289,12 +289,46 @@ static void swizzle_alsa_channels_6_##T(void *buffer, const Uint32 bufferlen) {
289289
} \
290290
}
291291

292-
SWIZ6(Uint64)
293-
SWIZ6(Uint32)
294-
SWIZ6(Uint16)
295-
SWIZ6(Uint8)
296292

293+
/* !!! FIXME: is there a channel swizzler in alsalib instead? */
294+
/* !!! FIXME: this screams for a SIMD shuffle operation. */
295+
/*
296+
* https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/mapping-stream-formats-to-speaker-configurations
297+
* For Linux ALSA, this appears to be FL-FR-RL-RR-C-LFE-SL-SR
298+
* and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-SL-SR-RL-RR"
299+
*/
300+
#define SWIZ8(T) \
301+
static void swizzle_alsa_channels_8_##T(void *buffer, const Uint32 bufferlen) { \
302+
T *ptr = (T *) buffer; \
303+
Uint32 i; \
304+
for (i = 0; i < bufferlen; i++, ptr += 6) { \
305+
const T center = ptr[2]; \
306+
const T subwoofer = ptr[3]; \
307+
const T side_left = ptr[4]; \
308+
const T side_right = ptr[5]; \
309+
const T rear_left = ptr[6]; \
310+
const T rear_right = ptr[7]; \
311+
ptr[2] = rear_left; \
312+
ptr[3] = rear_right; \
313+
ptr[4] = center; \
314+
ptr[5] = subwoofer; \
315+
ptr[6] = side_left; \
316+
ptr[7] = side_right; \
317+
} \
318+
}
319+
320+
#define CHANNEL_SWIZZLE(x) \
321+
x(Uint64) \
322+
x(Uint32) \
323+
x(Uint16) \
324+
x(Uint8)
325+
326+
CHANNEL_SWIZZLE(SWIZ6)
327+
CHANNEL_SWIZZLE(SWIZ8)
328+
329+
#undef CHANNEL_SWIZZLE
297330
#undef SWIZ6
331+
#undef SWIZ8
298332

299333

300334
/*
@@ -304,17 +338,23 @@ SWIZ6(Uint8)
304338
static void
305339
swizzle_alsa_channels(_THIS, void *buffer, Uint32 bufferlen)
306340
{
307-
if (this->spec.channels == 6) {
308-
switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
309-
case 8: swizzle_alsa_channels_6_Uint8(buffer, bufferlen); break;
310-
case 16: swizzle_alsa_channels_6_Uint16(buffer, bufferlen); break;
311-
case 32: swizzle_alsa_channels_6_Uint32(buffer, bufferlen); break;
312-
case 64: swizzle_alsa_channels_6_Uint64(buffer, bufferlen); break;
313-
default: SDL_assert(!"unhandled bitsize"); break;
314-
}
315-
}
341+
switch (this->spec.channels) {
342+
#define CHANSWIZ(chans) \
343+
case chans: \
344+
switch ((this->spec.format & (0xFF))) { \
345+
case 8: swizzle_alsa_channels_##chans##_Uint8(buffer, bufferlen); break; \
346+
case 16: swizzle_alsa_channels_##chans##_Uint16(buffer, bufferlen); break; \
347+
case 32: swizzle_alsa_channels_##chans##_Uint32(buffer, bufferlen); break; \
348+
case 64: swizzle_alsa_channels_##chans##_Uint64(buffer, bufferlen); break; \
349+
default: SDL_assert(!"unhandled bitsize"); break; \
350+
} \
351+
return;
316352

317-
/* !!! FIXME: update this for 7.1 if needed, later. */
353+
CHANSWIZ(6);
354+
CHANSWIZ(8);
355+
#undef CHANSWIZ
356+
default: break;
357+
}
318358
}
319359

320360
#ifdef SND_CHMAP_API_VERSION

0 commit comments

Comments
 (0)