/* Based off the speaker configurations mentioned here: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ksmedia/ns-ksmedia-ksaudio_channel_config */
/* Based off the speaker configurations mentioned here: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ksmedia/ns-ksmedia-ksaudio_channel_config */
switch (channels)
switch (channels)
{
{
case 1:
case 1:
{
{
channelMap[0] = MA_CHANNEL_MONO;
pChannelMap[0] = MA_CHANNEL_MONO;
} break;
} break;
case 2:
case 2:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
} break;
} break;
case 3: /* Not defined, but best guess. */
case 3: /* Not defined, but best guess. */
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
channelMap[2] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
} break;
} break;
case 4:
case 4:
{
{
#ifndef MA_USE_QUAD_MICROSOFT_CHANNEL_MAP
#ifndef MA_USE_QUAD_MICROSOFT_CHANNEL_MAP
/* Surround. Using the Surround profile has the advantage of the 3rd channel (MA_CHANNEL_FRONT_CENTER) mapping nicely with higher channel counts. */
/* Surround. Using the Surround profile has the advantage of the 3rd channel (MA_CHANNEL_FRONT_CENTER) mapping nicely with higher channel counts. */
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
channelMap[2] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
channelMap[3] = MA_CHANNEL_BACK_CENTER;
pChannelMap[3] = MA_CHANNEL_BACK_CENTER;
#else
#else
/* Quad. */
/* Quad. */
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
channelMap[2] = MA_CHANNEL_BACK_LEFT;
pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
channelMap[3] = MA_CHANNEL_BACK_RIGHT;
pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
#endif
#endif
} break;
} break;
case 5: /* Not defined, but best guess. */
case 5: /* Not defined, but best guess. */
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
channelMap[2] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
channelMap[3] = MA_CHANNEL_BACK_LEFT;
pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
channelMap[4] = MA_CHANNEL_BACK_RIGHT;
pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
} break;
} break;
case 6:
case 6:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
channelMap[2] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
channelMap[3] = MA_CHANNEL_LFE;
pChannelMap[3] = MA_CHANNEL_LFE;
channelMap[4] = MA_CHANNEL_SIDE_LEFT;
pChannelMap[4] = MA_CHANNEL_SIDE_LEFT;
channelMap[5] = MA_CHANNEL_SIDE_RIGHT;
pChannelMap[5] = MA_CHANNEL_SIDE_RIGHT;
} break;
} break;
case 7: /* Not defined, but best guess. */
case 7: /* Not defined, but best guess. */
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
channelMap[2] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
channelMap[3] = MA_CHANNEL_LFE;
pChannelMap[3] = MA_CHANNEL_LFE;
channelMap[4] = MA_CHANNEL_BACK_CENTER;
pChannelMap[4] = MA_CHANNEL_BACK_CENTER;
channelMap[5] = MA_CHANNEL_SIDE_LEFT;
pChannelMap[5] = MA_CHANNEL_SIDE_LEFT;
channelMap[6] = MA_CHANNEL_SIDE_RIGHT;
pChannelMap[6] = MA_CHANNEL_SIDE_RIGHT;
} break;
} break;
case 8:
case 8:
default:
default:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
channelMap[2] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[2] = MA_CHANNEL_FRONT_CENTER;
channelMap[3] = MA_CHANNEL_LFE;
pChannelMap[3] = MA_CHANNEL_LFE;
channelMap[4] = MA_CHANNEL_BACK_LEFT;
pChannelMap[4] = MA_CHANNEL_BACK_LEFT;
channelMap[5] = MA_CHANNEL_BACK_RIGHT;
pChannelMap[5] = MA_CHANNEL_BACK_RIGHT;
channelMap[6] = MA_CHANNEL_SIDE_LEFT;
pChannelMap[6] = MA_CHANNEL_SIDE_LEFT;
channelMap[7] = MA_CHANNEL_SIDE_RIGHT;
pChannelMap[7] = MA_CHANNEL_SIDE_RIGHT;
} break;
} break;
}
}
/* Remainder. */
/* Remainder. */
if (channels > 8) {
if (channels > 8) {
ma_uint32 iChannel;
ma_uint32 iChannel;
for (iChannel = 8; iChannel < MA_MAX_CHANNELS; ++iChannel) {
for (iChannel = 8; iChannel < channels; ++iChannel) {
/* In Vorbis' type 0 channel mapping, the first two channels are not always the standard left/right - it will have the center speaker where the right usually goes. Why?! */
/* In Vorbis' type 0 channel mapping, the first two channels are not always the standard left/right - it will have the center speaker where the right usually goes. Why?! */
switch (channels)
switch (channels)
{
{
case 1:
case 1:
{
{
channelMap[0] = MA_CHANNEL_MONO;
pChannelMap[0] = MA_CHANNEL_MONO;
} break;
} break;
case 2:
case 2:
{
{
channelMap[0] = MA_CHANNEL_LEFT;
pChannelMap[0] = MA_CHANNEL_LEFT;
channelMap[1] = MA_CHANNEL_RIGHT;
pChannelMap[1] = MA_CHANNEL_RIGHT;
} break;
} break;
case 3:
case 3:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
channelMap[2] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
} break;
} break;
case 4:
case 4:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[1] = MA_CHANNEL_FRONT_RIGHT;
channelMap[2] = MA_CHANNEL_BACK_LEFT;
pChannelMap[2] = MA_CHANNEL_BACK_LEFT;
channelMap[3] = MA_CHANNEL_BACK_RIGHT;
pChannelMap[3] = MA_CHANNEL_BACK_RIGHT;
} break;
} break;
case 5:
case 5:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
channelMap[2] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
channelMap[3] = MA_CHANNEL_BACK_LEFT;
pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
channelMap[4] = MA_CHANNEL_BACK_RIGHT;
pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
} break;
} break;
case 6:
case 6:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
channelMap[2] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
channelMap[3] = MA_CHANNEL_BACK_LEFT;
pChannelMap[3] = MA_CHANNEL_BACK_LEFT;
channelMap[4] = MA_CHANNEL_BACK_RIGHT;
pChannelMap[4] = MA_CHANNEL_BACK_RIGHT;
channelMap[5] = MA_CHANNEL_LFE;
pChannelMap[5] = MA_CHANNEL_LFE;
} break;
} break;
case 7:
case 7:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
channelMap[2] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
channelMap[3] = MA_CHANNEL_SIDE_LEFT;
pChannelMap[3] = MA_CHANNEL_SIDE_LEFT;
channelMap[4] = MA_CHANNEL_SIDE_RIGHT;
pChannelMap[4] = MA_CHANNEL_SIDE_RIGHT;
channelMap[5] = MA_CHANNEL_BACK_CENTER;
pChannelMap[5] = MA_CHANNEL_BACK_CENTER;
channelMap[6] = MA_CHANNEL_LFE;
pChannelMap[6] = MA_CHANNEL_LFE;
} break;
} break;
case 8:
case 8:
default:
default:
{
{
channelMap[0] = MA_CHANNEL_FRONT_LEFT;
pChannelMap[0] = MA_CHANNEL_FRONT_LEFT;
channelMap[1] = MA_CHANNEL_FRONT_CENTER;
pChannelMap[1] = MA_CHANNEL_FRONT_CENTER;
channelMap[2] = MA_CHANNEL_FRONT_RIGHT;
pChannelMap[2] = MA_CHANNEL_FRONT_RIGHT;
channelMap[3] = MA_CHANNEL_SIDE_LEFT;
pChannelMap[3] = MA_CHANNEL_SIDE_LEFT;
channelMap[4] = MA_CHANNEL_SIDE_RIGHT;
pChannelMap[4] = MA_CHANNEL_SIDE_RIGHT;
channelMap[5] = MA_CHANNEL_BACK_LEFT;
pChannelMap[5] = MA_CHANNEL_BACK_LEFT;
channelMap[6] = MA_CHANNEL_BACK_RIGHT;
pChannelMap[6] = MA_CHANNEL_BACK_RIGHT;
channelMap[7] = MA_CHANNEL_LFE;
pChannelMap[7] = MA_CHANNEL_LFE;
} break;
} break;
}
}
/* Remainder. */
/* Remainder. */
if (channels > 8) {
if (channels > 8) {
ma_uint32 iChannel;
ma_uint32 iChannel;
for (iChannel = 8; iChannel < MA_MAX_CHANNELS; ++iChannel) {
for (iChannel = 8; iChannel < channels; ++iChannel) {