From 73678f3b78a54d0dcc43abbd168ede2fd58bb205 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 31 Dec 2007 03:29:14 -0800 Subject: [PATCH] Allow psuedo 6.1 and 7.1 output This only does spatial calculations on the 4 corner speakers, but it's necessary groundwork for AL_EXT_MCFORMATS support. Spatial calculations for 6 speakers can be added later. --- Alc/ALu.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- openalrc.sample | 4 +++ 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index 682132e1..0473a4b0 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -64,6 +64,8 @@ typedef long long ALint64; enum { FRONT_LEFT = 0, FRONT_RIGHT, + SIDE_LEFT, + SIDE_RIGHT, BACK_LEFT, BACK_RIGHT, CENTER, @@ -72,6 +74,8 @@ enum { OUTPUTCHANNELS }; +/* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're + * converted to AL_FORMAT_QUAD* when loaded */ __inline ALuint aluBytesFromFormat(ALenum format) { switch(format) @@ -80,16 +84,24 @@ __inline ALuint aluBytesFromFormat(ALenum format) case AL_FORMAT_STEREO8: case AL_FORMAT_QUAD8: case AL_FORMAT_51CHN8: + case AL_FORMAT_61CHN8: + case AL_FORMAT_71CHN8: return 1; case AL_FORMAT_MONO16: case AL_FORMAT_STEREO16: case AL_FORMAT_QUAD16: case AL_FORMAT_51CHN16: + case AL_FORMAT_61CHN16: + case AL_FORMAT_71CHN16: return 2; case AL_FORMAT_MONO_FLOAT32: case AL_FORMAT_STEREO_FLOAT32: + case AL_FORMAT_QUAD32: + case AL_FORMAT_51CHN32: + case AL_FORMAT_61CHN32: + case AL_FORMAT_71CHN32: return 4; default: @@ -113,12 +125,24 @@ __inline ALuint aluChannelsFromFormat(ALenum format) case AL_FORMAT_QUAD8: case AL_FORMAT_QUAD16: + case AL_FORMAT_QUAD32: return 4; case AL_FORMAT_51CHN8: case AL_FORMAT_51CHN16: + case AL_FORMAT_51CHN32: return 6; + case AL_FORMAT_61CHN8: + case AL_FORMAT_61CHN16: + case AL_FORMAT_61CHN32: + return 7; + + case AL_FORMAT_71CHN8: + case AL_FORMAT_71CHN16: + case AL_FORMAT_71CHN32: + return 8; + default: return 0; } @@ -371,6 +395,9 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, case 4: /* TODO: Add center/lfe channel in spatial calculations? */ case 6: + /* TODO: Special paths for 6.1 and 7.1 output would be nice */ + case 7: + case 8: // Apply a scalar so each individual speaker has more weight PanningLR = 0.5f + (0.5f*Position[0]*1.41421356f); PanningLR = __min(1.0f, PanningLR); @@ -382,10 +409,14 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); drysend[BACK_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); drysend[BACK_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); + drysend[SIDE_LEFT] = 0.0f; + drysend[SIDE_RIGHT] = 0.0f; wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); wetsend[BACK_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); wetsend[BACK_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); + wetsend[SIDE_LEFT] = 0.0f; + wetsend[SIDE_RIGHT] = 0.0f; break; default: break; @@ -396,12 +427,16 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource, //1. Multi-channel buffers always play "normal" drysend[FRONT_LEFT] = SourceVolume * 1.0f * ListenerGain; drysend[FRONT_RIGHT] = SourceVolume * 1.0f * ListenerGain; + drysend[SIDE_LEFT] = SourceVolume * 1.0f * ListenerGain; + drysend[SIDE_RIGHT] = SourceVolume * 1.0f * ListenerGain; drysend[BACK_LEFT] = SourceVolume * 1.0f * ListenerGain; drysend[BACK_RIGHT] = SourceVolume * 1.0f * ListenerGain; drysend[CENTER] = SourceVolume * 1.0f * ListenerGain; drysend[LFE] = SourceVolume * 1.0f * ListenerGain; wetsend[FRONT_LEFT] = SourceVolume * 0.0f * ListenerGain; wetsend[FRONT_RIGHT] = SourceVolume * 0.0f * ListenerGain; + wetsend[SIDE_LEFT] = SourceVolume * 0.0f * ListenerGain; + wetsend[SIDE_RIGHT] = SourceVolume * 0.0f * ListenerGain; wetsend[BACK_LEFT] = SourceVolume * 0.0f * ListenerGain; wetsend[BACK_RIGHT] = SourceVolume * 0.0f * ListenerGain; wetsend[CENTER] = SourceVolume * 0.0f * ListenerGain; @@ -415,8 +450,8 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma { static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS]; static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS]; - ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + ALfloat DrySend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + ALfloat WetSend[OUTPUTCHANNELS] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; ALuint BlockAlign,BufferSize; ALuint DataSize=0,DataPosInt=0,DataPosFrac=0; ALuint Channels,Bits,Frequency,ulExtraSamples; @@ -543,11 +578,15 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma //Direct path final mix buffer and panning DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT]; DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT]; + DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT]; + DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT]; DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT]; DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT]; //Room path final mix buffer and panning WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT]; WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT]; + WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT]; + WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT]; WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT]; WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT]; } @@ -693,6 +732,34 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma buffer = ((ALubyte*)buffer) + 6; } break; + case AL_FORMAT_61CHN8: + for(i = 0;i < SamplesToDo;i++) + { + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128); + ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128); + ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128); + ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128); + ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128); + ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128); + buffer = ((ALubyte*)buffer) + 7; + } + break; + case AL_FORMAT_71CHN8: + for(i = 0;i < SamplesToDo;i++) + { + ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT])>>8)+128); + ((ALubyte*)buffer)[1] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT])>>8)+128); + ((ALubyte*)buffer)[2] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT])>>8)+128); + ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT])>>8)+128); + ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128); + ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128); + ((ALubyte*)buffer)[6] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128); + ((ALubyte*)buffer)[7] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128); + buffer = ((ALubyte*)buffer) + 8; + } + break; + case AL_FORMAT_MONO16: for(i = 0;i < SamplesToDo;i++) { @@ -731,6 +798,33 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma buffer = ((ALshort*)buffer) + 6; } break; + case AL_FORMAT_61CHN16: + for(i = 0;i < SamplesToDo;i++) + { + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]); + ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]); + ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]); + ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]); + ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]); + ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]); + buffer = ((ALshort*)buffer) + 7; + } + break; + case AL_FORMAT_71CHN16: + for(i = 0;i < SamplesToDo;i++) + { + ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]); + ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]); + ((ALshort*)buffer)[2] = aluF2S(DryBuffer[i][SIDE_LEFT] +WetBuffer[i][SIDE_LEFT]); + ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][SIDE_RIGHT] +WetBuffer[i][SIDE_RIGHT]); + ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][BACK_LEFT] +WetBuffer[i][BACK_LEFT]); + ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]); + ((ALshort*)buffer)[6] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]); + ((ALshort*)buffer)[7] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]); + buffer = ((ALshort*)buffer) + 8; + } + break; default: break; diff --git a/openalrc.sample b/openalrc.sample index c456d544..cb4b28dc 100644 --- a/openalrc.sample +++ b/openalrc.sample @@ -13,10 +13,14 @@ format = AL_FORMAT_STEREO16 # Sets the output format. Can be one of: # AL_FORMAT_STEREO8 (8-bit stereo) # AL_FORMAT_QUAD8 (8-bit 4-channel) # AL_FORMAT_51CHN8 (8-bit 5.1 output) + # AL_FORMAT_61CHN8 (8-bit 6.1 output) + # AL_FORMAT_71CHN8 (8-bit 7.1 output) # AL_FORMAT_MONO16 (16-bit mono) # AL_FORMAT_STEREO16 (16-bit stereo) # AL_FORMAT_QUAD16 (16-bit 4-channel) # AL_FORMAT_51CHN16 (16-bit 5.1 output) + # AL_FORMAT_61CHN16 (16-bit 6.1 output) + # AL_FORMAT_71CHN16 (16-bit 7.1 output) # Default is AL_FORMAT_STEREO16 frequency = 44100 # Sets the output frequency. Default is 44100 -- 2.11.4.GIT