From f82c88f01693c3a70428b3ee4311345ffbbee7d9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sun, 25 Jan 2009 19:20:47 -0800 Subject: [PATCH] Add options for user-configurable speaker arrangements --- Alc/ALu.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ alsoftrc.sample | 36 +++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/Alc/ALu.c b/Alc/ALu.c index da5122b4..e29cb025 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -25,6 +25,8 @@ #include #include #include +#include + #include "alMain.h" #include "AL/al.h" #include "AL/alc.h" @@ -259,6 +261,87 @@ static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3]) memcpy(vector, result, sizeof(result)); } +static ALvoid SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[OUTPUTCHANNELS], + ALint Speaker2Chan[OUTPUTCHANNELS], ALint chans) +{ + const char *confkey; + const char *next; + const char *sep; + const char *end; + int i, val; + + confkey = GetConfigValue(NULL, name, ""); + next = confkey; + while(next && *next) + { + confkey = next; + next = strchr(confkey, ','); + if(next) + { + do { + next++; + } while(isspace(*next)); + } + + sep = strchr(confkey, '='); + if(!sep || confkey == sep) + continue; + + end = sep - 1; + while(isspace(*end) && end != confkey) + end--; + + if(strncmp(confkey, "fl", end-confkey) == 0) + val = FRONT_LEFT; + else if(strncmp(confkey, "fr", end-confkey) == 0) + val = FRONT_RIGHT; + else if(strncmp(confkey, "fc", end-confkey) == 0) + val = FRONT_CENTER; + else if(strncmp(confkey, "bl", end-confkey) == 0) + val = BACK_LEFT; + else if(strncmp(confkey, "br", end-confkey) == 0) + val = BACK_RIGHT; + else if(strncmp(confkey, "bc", end-confkey) == 0) + val = BACK_CENTER; + else if(strncmp(confkey, "sl", end-confkey) == 0) + val = SIDE_LEFT; + else if(strncmp(confkey, "sr", end-confkey) == 0) + val = SIDE_RIGHT; + else + { + AL_PRINT("Unknown speaker for %s: \"%c%c\"\n", name, confkey[0], confkey[1]); + continue; + } + + sep++; + while(isspace(*sep)) + sep++; + + for(i = 0;i < chans;i++) + { + if(Speaker2Chan[i] == val) + { + val = strtol(sep, NULL, 10); + if(val >= -180 && val <= 180) + SpeakerAngle[i] = val * M_PI/180.0f; + else + AL_PRINT("Invalid angle for speaker \"%c%c\": %d\n", confkey[0], confkey[1], val); + break; + } + } + } + + for(i = 1;i < chans;i++) + { + if(SpeakerAngle[i] <= SpeakerAngle[i-1]) + { + AL_PRINT("Speaker %d of %d does not follow previous: %f > %f\n", i, chans, + SpeakerAngle[i-1] * 180.0f/M_PI, SpeakerAngle[i] * 180.0f/M_PI); + SpeakerAngle[i] = SpeakerAngle[i-1] + 1 * 180.0f/M_PI; + } + } +} + static __inline ALfloat aluLUTpos2Angle(ALint pos) { if(pos < QUADRANT_NUM) @@ -291,6 +374,8 @@ ALvoid aluInitPanning(ALCcontext *Context) Speaker2Chan[1] = FRONT_RIGHT; SpeakerAngle[0] = -90.0f * M_PI/180.0f; SpeakerAngle[1] = 90.0f * M_PI/180.0f; + SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Context->NumChan); + break; case AL_FORMAT_QUAD8: case AL_FORMAT_QUAD16: @@ -304,6 +389,7 @@ ALvoid aluInitPanning(ALCcontext *Context) SpeakerAngle[1] = -45.0f * M_PI/180.0f; SpeakerAngle[2] = 45.0f * M_PI/180.0f; SpeakerAngle[3] = 135.0f * M_PI/180.0f; + SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Context->NumChan); break; case AL_FORMAT_51CHN8: @@ -320,6 +406,7 @@ ALvoid aluInitPanning(ALCcontext *Context) SpeakerAngle[2] = 0.0f * M_PI/180.0f; SpeakerAngle[3] = 30.0f * M_PI/180.0f; SpeakerAngle[4] = 110.0f * M_PI/180.0f; + SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Context->NumChan); break; case AL_FORMAT_61CHN8: @@ -338,6 +425,7 @@ ALvoid aluInitPanning(ALCcontext *Context) SpeakerAngle[3] = 30.0f * M_PI/180.0f; SpeakerAngle[4] = 90.0f * M_PI/180.0f; SpeakerAngle[5] = 180.0f * M_PI/180.0f; + SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Context->NumChan); break; case AL_FORMAT_71CHN8: @@ -358,6 +446,7 @@ ALvoid aluInitPanning(ALCcontext *Context) SpeakerAngle[4] = 30.0f * M_PI/180.0f; SpeakerAngle[5] = 90.0f * M_PI/180.0f; SpeakerAngle[6] = 150.0f * M_PI/180.0f; + SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Context->NumChan); break; default: diff --git a/alsoftrc.sample b/alsoftrc.sample index e447d528..5b10f18f 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -67,6 +67,42 @@ excludefx = # Sets which effects to exclude, preventing apps from using them. # reverb # Default is empty (all available effects enabled) +layout_STEREO = # Sets the speaker layout when using stereo output. Values are + specified in degrees, where 0 is straight in front, negative + goes left, and positive goes right. The values must define a + circular pattern, starting with the back-left at the most + negative, around the front to back-center. Unspecified + speakers will remain at their default position. Available + speakers are front-left(fl) and front-right(fr). + The default is: + fl=-90, fr=90 + +layout_QUAD = # Sets the speaker layout when using quadriphonic output. + Available speakers are back-left(bl), front-left(fl), + front-right(fr), and back-right(br). + The default is: + bl=-135, fl=-45, fr=45, br=135 + +layout_51CHN = # Sets the speaker layout when using 5.1 output. Available + speakers are back-left(bl), front-left(fl), front-center(fc), + front-right(fr), and back-right(br). + The default is: + bl=-110, fl=-30, fc=0, fr=30, br=110 + +layout_61CHN = # Sets the speaker layout when using 6.1 output. Available + speakers are side-left(sl), front-left(fl), front-center(fc), + front-right(fr), side-right(sr), and back-center(bc). + The default is: + sl=-90, fl=-30, fc=0, fr=30, sr=90, bc=180 + +layout_71CHN = # Sets the speaker layout when using 7.1 output. Available + speakers are back-left(bl), side-left(sl), front-left(fl), + front-center(fc), front-right(fr), side-right(sr), and + back-right(br). + The default is: + bl=-150, sl=-90, fl=-30, fc=0, fr=30, sr=90 br=150 + + [alsa] # ALSA backend stuff device = default # Sets the device name for the default playback device. # Default is default -- 2.11.4.GIT