From b5270e0bb300f090c159803e79b50ba15b821b2e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Wed, 2 Dec 2009 04:03:51 -0800 Subject: [PATCH] Use a channel-map to specify the output device channel order --- Alc/ALu.c | 93 +++++++++++++++++++---------------------------- Alc/alsa.c | 2 + Alc/dsound.c | 1 + Alc/oss.c | 2 + Alc/portaudio.c | 2 + Alc/pulseaudio.c | 29 +-------------- Alc/solaris.c | 2 + Alc/wave.c | 2 + OpenAL32/Include/alMain.h | 81 +++++++++++++++++++++++++++++++++++++++++ OpenAL32/Include/alu.h | 4 +- 10 files changed, 132 insertions(+), 86 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index ce0f841c..36cc4046 100644 --- a/Alc/ALu.c +++ b/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 diff --git a/Alc/alsa.c b/Alc/alsa.c index 85092ceb..25956746 100644 --- a/Alc/alsa.c +++ b/Alc/alsa.c @@ -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) { diff --git a/Alc/dsound.c b/Alc/dsound.c index e6294a43..966b6236 100644 --- a/Alc/dsound.c +++ b/Alc/dsound.c @@ -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; diff --git a/Alc/oss.c b/Alc/oss.c index 94380fde..64cf23c6 100644 --- a/Alc/oss.c +++ b/Alc/oss.c @@ -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) { diff --git a/Alc/portaudio.c b/Alc/portaudio.c index 5c90f611..580cc4fb 100644 --- a/Alc/portaudio.c +++ b/Alc/portaudio.c @@ -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) diff --git a/Alc/pulseaudio.c b/Alc/pulseaudio.c index 42ed84f3..3b83d127 100644 --- a/Alc/pulseaudio.c +++ b/Alc/pulseaudio.c @@ -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) diff --git a/Alc/solaris.c b/Alc/solaris.c index a6a0dda4..4504a680 100644 --- a/Alc/solaris.c +++ b/Alc/solaris.c @@ -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) { diff --git a/Alc/wave.c b/Alc/wave.c index 8de3a623..1d2a39d2 100644 --- a/Alc/wave.c +++ b/Alc/wave.c @@ -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) { diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 69bd9d5b..4094d894 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -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 diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index 978527e5..acf1b480 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -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 -- 2.11.4.GIT