Use a channel-map to specify the output device channel order
This commit is contained in:
parent
6cfc31777b
commit
b5270e0bb3
93
Alc/ALu.c
93
Alc/ALu.c
@ -1231,6 +1231,7 @@ another_source:
|
||||
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
{
|
||||
float (*DryBuffer)[OUTPUTCHANNELS];
|
||||
const Channel *ChanMap;
|
||||
ALuint SamplesToDo;
|
||||
ALeffectslot *ALEffectSlot;
|
||||
ALCcontext *ALContext;
|
||||
@ -1280,14 +1281,15 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
}
|
||||
|
||||
//Post processing loop
|
||||
ChanMap = device->DevChannels;
|
||||
switch(device->Format)
|
||||
{
|
||||
#define CHECK_WRITE_FORMAT(bits, type, func, isWin) \
|
||||
#define CHECK_WRITE_FORMAT(bits, type, func) \
|
||||
case AL_FORMAT_MONO##bits: \
|
||||
for(i = 0;i < SamplesToDo;i++) \
|
||||
{ \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][FRONT_LEFT] + \
|
||||
DryBuffer[i][FRONT_RIGHT]); \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][ChanMap[0]] + \
|
||||
DryBuffer[i][ChanMap[1]]); \
|
||||
buffer = ((type*)buffer) + 1; \
|
||||
} \
|
||||
break; \
|
||||
@ -1297,8 +1299,8 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
for(i = 0;i < SamplesToDo;i++) \
|
||||
{ \
|
||||
float samples[2]; \
|
||||
samples[0] = DryBuffer[i][FRONT_LEFT]; \
|
||||
samples[1] = DryBuffer[i][FRONT_RIGHT]; \
|
||||
samples[0] = DryBuffer[i][ChanMap[0]]; \
|
||||
samples[1] = DryBuffer[i][ChanMap[1]]; \
|
||||
bs2b_cross_feed(device->Bs2b, samples); \
|
||||
((type*)buffer)[0] = (func)(samples[0]); \
|
||||
((type*)buffer)[1] = (func)(samples[1]); \
|
||||
@ -1309,8 +1311,8 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
{ \
|
||||
for(i = 0;i < SamplesToDo;i++) \
|
||||
{ \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][FRONT_LEFT]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][FRONT_RIGHT]); \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][ChanMap[0]]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][ChanMap[1]]); \
|
||||
buffer = ((type*)buffer) + 2; \
|
||||
} \
|
||||
} \
|
||||
@ -1318,79 +1320,58 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
|
||||
case AL_FORMAT_QUAD##bits: \
|
||||
for(i = 0;i < SamplesToDo;i++) \
|
||||
{ \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][FRONT_LEFT]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][FRONT_RIGHT]); \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][BACK_LEFT]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][BACK_RIGHT]); \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][ChanMap[0]]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][ChanMap[1]]); \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][ChanMap[2]]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][ChanMap[3]]); \
|
||||
buffer = ((type*)buffer) + 4; \
|
||||
} \
|
||||
break; \
|
||||
case AL_FORMAT_51CHN##bits: \
|
||||
for(i = 0;i < SamplesToDo;i++) \
|
||||
{ \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][FRONT_LEFT]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][FRONT_RIGHT]); \
|
||||
if(isWin) { \
|
||||
/* Of course, Windows can't use the same ordering... */ \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][FRONT_CENTER]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][LFE]); \
|
||||
((type*)buffer)[4] = (func)(DryBuffer[i][BACK_LEFT]); \
|
||||
((type*)buffer)[5] = (func)(DryBuffer[i][BACK_RIGHT]); \
|
||||
} else { \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][BACK_LEFT]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][BACK_RIGHT]); \
|
||||
((type*)buffer)[4] = (func)(DryBuffer[i][FRONT_CENTER]); \
|
||||
((type*)buffer)[5] = (func)(DryBuffer[i][LFE]); \
|
||||
} \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][ChanMap[0]]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][ChanMap[1]]); \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][ChanMap[2]]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][ChanMap[3]]); \
|
||||
((type*)buffer)[4] = (func)(DryBuffer[i][ChanMap[4]]); \
|
||||
((type*)buffer)[5] = (func)(DryBuffer[i][ChanMap[5]]); \
|
||||
buffer = ((type*)buffer) + 6; \
|
||||
} \
|
||||
break; \
|
||||
case AL_FORMAT_61CHN##bits: \
|
||||
for(i = 0;i < SamplesToDo;i++) \
|
||||
{ \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][FRONT_LEFT]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][FRONT_RIGHT]); \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][FRONT_CENTER]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][LFE]); \
|
||||
((type*)buffer)[4] = (func)(DryBuffer[i][BACK_CENTER]); \
|
||||
((type*)buffer)[5] = (func)(DryBuffer[i][SIDE_LEFT]); \
|
||||
((type*)buffer)[6] = (func)(DryBuffer[i][SIDE_RIGHT]); \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][ChanMap[0]]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][ChanMap[1]]); \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][ChanMap[2]]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][ChanMap[3]]); \
|
||||
((type*)buffer)[4] = (func)(DryBuffer[i][ChanMap[4]]); \
|
||||
((type*)buffer)[5] = (func)(DryBuffer[i][ChanMap[5]]); \
|
||||
((type*)buffer)[6] = (func)(DryBuffer[i][ChanMap[6]]); \
|
||||
buffer = ((type*)buffer) + 7; \
|
||||
} \
|
||||
break; \
|
||||
case AL_FORMAT_71CHN##bits: \
|
||||
for(i = 0;i < SamplesToDo;i++) \
|
||||
{ \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][FRONT_LEFT]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][FRONT_RIGHT]); \
|
||||
if(isWin) { \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][FRONT_CENTER]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][LFE]); \
|
||||
((type*)buffer)[4] = (func)(DryBuffer[i][BACK_LEFT]); \
|
||||
((type*)buffer)[5] = (func)(DryBuffer[i][BACK_RIGHT]); \
|
||||
} else { \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][BACK_LEFT]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][BACK_RIGHT]); \
|
||||
((type*)buffer)[4] = (func)(DryBuffer[i][FRONT_CENTER]); \
|
||||
((type*)buffer)[5] = (func)(DryBuffer[i][LFE]); \
|
||||
} \
|
||||
((type*)buffer)[6] = (func)(DryBuffer[i][SIDE_LEFT]); \
|
||||
((type*)buffer)[7] = (func)(DryBuffer[i][SIDE_RIGHT]); \
|
||||
((type*)buffer)[0] = (func)(DryBuffer[i][ChanMap[0]]); \
|
||||
((type*)buffer)[1] = (func)(DryBuffer[i][ChanMap[1]]); \
|
||||
((type*)buffer)[2] = (func)(DryBuffer[i][ChanMap[2]]); \
|
||||
((type*)buffer)[3] = (func)(DryBuffer[i][ChanMap[3]]); \
|
||||
((type*)buffer)[4] = (func)(DryBuffer[i][ChanMap[4]]); \
|
||||
((type*)buffer)[5] = (func)(DryBuffer[i][ChanMap[5]]); \
|
||||
((type*)buffer)[6] = (func)(DryBuffer[i][ChanMap[6]]); \
|
||||
((type*)buffer)[7] = (func)(DryBuffer[i][ChanMap[7]]); \
|
||||
buffer = ((type*)buffer) + 8; \
|
||||
} \
|
||||
break;
|
||||
|
||||
#define AL_FORMAT_MONO32 AL_FORMAT_MONO_FLOAT32
|
||||
#define AL_FORMAT_STEREO32 AL_FORMAT_STEREO_FLOAT32
|
||||
#ifdef _WIN32
|
||||
CHECK_WRITE_FORMAT(8, ALubyte, aluF2UB, 1)
|
||||
CHECK_WRITE_FORMAT(16, ALshort, aluF2S, 1)
|
||||
CHECK_WRITE_FORMAT(32, ALfloat, aluF2F, 1)
|
||||
#else
|
||||
CHECK_WRITE_FORMAT(8, ALubyte, aluF2UB, 0)
|
||||
CHECK_WRITE_FORMAT(16, ALshort, aluF2S, 0)
|
||||
CHECK_WRITE_FORMAT(32, ALfloat, aluF2F, 0)
|
||||
#endif
|
||||
CHECK_WRITE_FORMAT(8, ALubyte, aluF2UB)
|
||||
CHECK_WRITE_FORMAT(16, ALshort, aluF2S)
|
||||
CHECK_WRITE_FORMAT(32, ALfloat, aluF2F)
|
||||
#undef AL_FORMAT_STEREO32
|
||||
#undef AL_FORMAT_MONO32
|
||||
#undef CHECK_WRITE_FORMAT
|
||||
|
@ -663,6 +663,8 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
|
||||
|
||||
psnd_pcm_sw_params_free(sp);
|
||||
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames);
|
||||
if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
|
||||
{
|
||||
|
@ -415,6 +415,7 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
device->Format = format;
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
pData->thread = StartThread(DSoundProc, device);
|
||||
if(!pData->thread)
|
||||
hr = E_FAIL;
|
||||
|
@ -274,6 +274,8 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
|
||||
data->data_size = device->UpdateSize * frameSize;
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
data->thread = StartThread(OSSProc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
|
@ -189,6 +189,8 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
}
|
||||
outParams.channelCount = aluChannelsFromFormat(device->Format);
|
||||
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
|
||||
device->UpdateSize, paNoFlag, pa_callback, device);
|
||||
if(err != paNoError)
|
||||
|
@ -518,40 +518,13 @@ static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if(!ppa_channel_map_init_auto(&chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX))
|
||||
{
|
||||
AL_PRINT("Couldn't build map for channel count (%d)!", data->spec.channels);
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
#else
|
||||
switch(data->spec.channels)
|
||||
{
|
||||
case 1:
|
||||
ppa_channel_map_parse(&chanmap, "mono");
|
||||
break;
|
||||
case 2:
|
||||
ppa_channel_map_parse(&chanmap, "front-left,front-right");
|
||||
break;
|
||||
case 4:
|
||||
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right");
|
||||
break;
|
||||
case 6:
|
||||
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right,front-center,lfe");
|
||||
break;
|
||||
case 7:
|
||||
ppa_channel_map_parse(&chanmap, "front-left,front-right,front-center,lfe,rear-center,side-left,side-right");
|
||||
break;
|
||||
case 8:
|
||||
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right");
|
||||
break;
|
||||
default:
|
||||
AL_PRINT("Got unhandled channel count (%d)!", data->spec.channels);
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
#endif
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
|
||||
data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, &chanmap);
|
||||
if(!data->stream)
|
||||
|
@ -197,6 +197,8 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
|
||||
data->data_size = device->UpdateSize * frameSize;
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
SetDefaultChannelOrder(device);
|
||||
|
||||
data->thread = StartThread(SolarisProc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
|
@ -227,6 +227,8 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
SetDefaultWFXChannelOrder(device);
|
||||
|
||||
data->thread = StartThread(WaveProc, device);
|
||||
if(data->thread == NULL)
|
||||
{
|
||||
|
@ -272,6 +272,8 @@ struct ALCdevice_struct
|
||||
// Dry path buffer mix
|
||||
float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
|
||||
|
||||
Channel DevChannels[OUTPUTCHANNELS];
|
||||
|
||||
// Contexts created on this device
|
||||
ALCcontext **Contexts;
|
||||
ALuint NumContexts;
|
||||
@ -364,6 +366,85 @@ void EnableRTPrio(ALint level);
|
||||
ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context);
|
||||
ALCcontext* ALCAPIENTRY alcGetThreadContext(void);
|
||||
|
||||
// Sets the default channel order used by most non-WaveFormatEx-based APIs
|
||||
static __inline void SetDefaultChannelOrder(ALCdevice *device)
|
||||
{
|
||||
switch(aluChannelsFromFormat(device->Format))
|
||||
{
|
||||
case 1: /* Mono is rendered as stereo; fall-through... */
|
||||
case 2: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT; break;
|
||||
|
||||
case 4: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT;
|
||||
device->DevChannels[2] = BACK_LEFT;
|
||||
device->DevChannels[3] = BACK_RIGHT; break;
|
||||
|
||||
case 6: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT;
|
||||
device->DevChannels[2] = BACK_LEFT;
|
||||
device->DevChannels[3] = BACK_RIGHT;
|
||||
device->DevChannels[4] = FRONT_CENTER;
|
||||
device->DevChannels[5] = LFE; break;
|
||||
|
||||
case 7: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT;
|
||||
device->DevChannels[2] = FRONT_CENTER;
|
||||
device->DevChannels[3] = LFE;
|
||||
device->DevChannels[4] = FRONT_CENTER;
|
||||
device->DevChannels[5] = SIDE_LEFT;
|
||||
device->DevChannels[6] = SIDE_RIGHT; break;
|
||||
|
||||
case 8: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT;
|
||||
device->DevChannels[2] = BACK_LEFT;
|
||||
device->DevChannels[3] = BACK_RIGHT;
|
||||
device->DevChannels[4] = FRONT_CENTER;
|
||||
device->DevChannels[5] = LFE;
|
||||
device->DevChannels[6] = SIDE_LEFT;
|
||||
device->DevChannels[7] = SIDE_RIGHT; break;
|
||||
}
|
||||
}
|
||||
// Sets the default order used by WaveFormatEx
|
||||
static __inline void SetDefaultWFXChannelOrder(ALCdevice *device)
|
||||
{
|
||||
switch(aluChannelsFromFormat(device->Format))
|
||||
{
|
||||
case 1: /* Mono is rendered as stereo; fall-through... */
|
||||
case 2: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT; break;
|
||||
|
||||
case 4: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT;
|
||||
device->DevChannels[2] = BACK_LEFT;
|
||||
device->DevChannels[3] = BACK_RIGHT; break;
|
||||
|
||||
case 6: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT;
|
||||
device->DevChannels[2] = FRONT_CENTER;
|
||||
device->DevChannels[3] = LFE;
|
||||
device->DevChannels[4] = BACK_LEFT;
|
||||
device->DevChannels[5] = BACK_RIGHT; break;
|
||||
|
||||
case 7: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT;
|
||||
device->DevChannels[2] = FRONT_CENTER;
|
||||
device->DevChannels[3] = LFE;
|
||||
device->DevChannels[4] = FRONT_CENTER;
|
||||
device->DevChannels[5] = SIDE_LEFT;
|
||||
device->DevChannels[6] = SIDE_RIGHT; break;
|
||||
|
||||
case 8: device->DevChannels[0] = FRONT_LEFT;
|
||||
device->DevChannels[1] = FRONT_RIGHT;
|
||||
device->DevChannels[2] = FRONT_CENTER;
|
||||
device->DevChannels[3] = LFE;
|
||||
device->DevChannels[4] = BACK_LEFT;
|
||||
device->DevChannels[5] = BACK_RIGHT;
|
||||
device->DevChannels[6] = SIDE_LEFT;
|
||||
device->DevChannels[7] = SIDE_RIGHT; break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -54,7 +54,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
FRONT_LEFT = 0,
|
||||
FRONT_RIGHT,
|
||||
FRONT_CENTER,
|
||||
@ -66,7 +66,7 @@ enum {
|
||||
LFE,
|
||||
|
||||
OUTPUTCHANNELS
|
||||
};
|
||||
} Channel;
|
||||
|
||||
#define BUFFERSIZE 24000
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user