summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2007-12-31 19:34:52 -0800
committerChris Robinson <[email protected]>2007-12-31 19:34:52 -0800
commit3d78d93b4033ea94d38981e75f10c6dee5264860 (patch)
treeeff0ee8b22ea032075fd16046d6cb24fa52a8243
parent5a2f509104b196bbef336b6c772cd621473f2e55 (diff)
parent9382956b0ec459a696805a23656a9e94b6ed94d9 (diff)
Merge branch 'master' into efx-experiment
-rw-r--r--Alc/ALc.c11
-rw-r--r--Alc/ALu.c360
-rw-r--r--Alc/alsa.c129
-rw-r--r--Alc/dsound.c2
-rw-r--r--Alc/oss.c20
-rw-r--r--CMakeLists.txt35
-rw-r--r--OpenAL32/Include/alMain.h37
-rw-r--r--OpenAL32/Include/alSource.h4
-rw-r--r--OpenAL32/Include/alu.h6
-rw-r--r--OpenAL32/alAuxEffectSlot.c2
-rw-r--r--OpenAL32/alBuffer.c278
-rw-r--r--OpenAL32/alEffect.c2
-rw-r--r--OpenAL32/alExtension.c16
-rw-r--r--OpenAL32/alFilter.c2
-rw-r--r--OpenAL32/alSource.c71
-rw-r--r--openalrc.sample6
16 files changed, 758 insertions, 223 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 8c824a2d..681d1a66 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -30,6 +30,9 @@
#include "alSource.h"
#include "AL/al.h"
#include "AL/alc.h"
+#include "alThunk.h"
+#include "alSource.h"
+#include "alExtension.h"
///////////////////////////////////////////////////////
// DEBUG INFORMATION
@@ -371,7 +374,7 @@ static ALvoid InitContext(ALCcontext *pContext)
pContext->lNumStereoSources = 1;
pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
- strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET");
+ strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET");
}
@@ -423,6 +426,9 @@ ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, AL
InitAL();
+ if(deviceName && !deviceName[0])
+ deviceName = NULL;
+
pDevice = malloc(sizeof(ALCdevice));
if (pDevice)
{
@@ -1072,6 +1078,9 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
InitAL();
+ if(deviceName && !deviceName[0])
+ deviceName = NULL;
+
device = malloc(sizeof(ALCdevice));
if (device)
{
diff --git a/Alc/ALu.c b/Alc/ALu.c
index a0c89852..f401046c 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -26,6 +26,10 @@
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
+#include "alSource.h"
+#include "alBuffer.h"
+#include "alThunk.h"
+#include "alListener.h"
#if defined(HAVE_STDINT_H)
#include <stdint.h>
@@ -52,6 +56,26 @@ typedef long long ALint64;
#define __min min
#endif
+#define BUFFERSIZE 48000
+#define FRACTIONBITS 14
+#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
+#define MAX_PITCH 4
+
+enum {
+ FRONT_LEFT = 0,
+ FRONT_RIGHT,
+ SIDE_LEFT,
+ SIDE_RIGHT,
+ BACK_LEFT,
+ BACK_RIGHT,
+ CENTER,
+ LFE,
+
+ 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)
@@ -59,13 +83,27 @@ __inline ALuint aluBytesFromFormat(ALenum format)
case AL_FORMAT_MONO8:
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:
return 0;
}
@@ -77,16 +115,34 @@ __inline ALuint aluChannelsFromFormat(ALenum format)
{
case AL_FORMAT_MONO8:
case AL_FORMAT_MONO16:
+ case AL_FORMAT_MONO_FLOAT32:
return 1;
case AL_FORMAT_STEREO8:
case AL_FORMAT_STEREO16:
+ case AL_FORMAT_STEREO_FLOAT32:
return 2;
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;
}
@@ -405,43 +461,45 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
//7. Convert normalized position into pannings, then into channel volumes
aluNormalize(Position);
WetMix *= ALSource->Send[0].Slot.Gain;
- switch(OutputFormat)
+ switch(aluChannelsFromFormat(OutputFormat))
{
- case AL_FORMAT_MONO8:
- case AL_FORMAT_MONO16:
- drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
- drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
+ case 1:
+ drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
+ drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f); //Direct
if(ALSource->Send[0].Slot.effectslot)
{
- wetsend[0] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
- wetsend[1] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
+ wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
+ wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(1.0f); //Room
}
else
{
- wetsend[0] = 0.0f;
- wetsend[1] = 0.0f;
+ wetsend[FRONT_LEFT] = 0.0f;
+ wetsend[FRONT_RIGHT] = 0.0f;
*wetgainhf = 1.0f;
}
break;
- case AL_FORMAT_STEREO8:
- case AL_FORMAT_STEREO16:
+ case 2:
PanningLR = 0.5f + 0.5f*Position[0];
- drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f-PanningLR); //L Direct
- drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt( PanningLR); //R Direct
+ drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt(1.0f-PanningLR); //L Direct
+ drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt( PanningLR); //R Direct
if(ALSource->Send[0].Slot.effectslot)
{
- wetsend[0] = ListenerGain * WetMix * aluSqrt(1.0f-PanningLR); //L Room
- wetsend[1] = ListenerGain * WetMix * aluSqrt( PanningLR); //R Room
+ wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt(1.0f-PanningLR); //L Room
+ wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt( PanningLR); //R Room
}
else
{
- wetsend[0] = 0.0f;
- wetsend[1] = 0.0f;
+ wetsend[FRONT_LEFT] = 0.0f;
+ wetsend[FRONT_RIGHT] = 0.0f;
*wetgainhf = 1.0f;
}
break;
- case AL_FORMAT_QUAD8:
- case AL_FORMAT_QUAD16:
+ 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);
@@ -449,25 +507,29 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
PanningFB = 0.5f + (0.5f*Position[2]*1.41421356f);
PanningFB = __min(1.0f, PanningFB);
PanningFB = __max(0.0f, PanningFB);
- drysend[0] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Direct
- drysend[1] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Direct
- drysend[2] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Direct
- drysend[3] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Direct
+ drysend[FRONT_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Direct
+ drysend[FRONT_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Direct
+ drysend[BACK_LEFT] = ConeVolume * ListenerGain * DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Direct
+ drysend[BACK_RIGHT] = ConeVolume * ListenerGain * DryMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Direct
+ drysend[SIDE_LEFT] = 0.0f;
+ drysend[SIDE_RIGHT] = 0.0f;
if(ALSource->Send[0].Slot.effectslot)
{
- wetsend[0] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Room
- wetsend[1] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Room
- wetsend[2] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Room
- wetsend[3] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Room
+ wetsend[FRONT_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB)); //FL Room
+ wetsend[FRONT_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB)); //FR Room
+ wetsend[BACK_LEFT] = ListenerGain * WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB)); //BL Room
+ wetsend[BACK_RIGHT] = ListenerGain * WetMix * aluSqrt(( PanningLR)*( PanningFB)); //BR Room
}
else
{
- wetsend[0] = 0.0f;
- wetsend[1] = 0.0f;
- wetsend[2] = 0.0f;
- wetsend[3] = 0.0f;
+ wetsend[FRONT_LEFT] = 0.0f;
+ wetsend[FRONT_RIGHT] = 0.0f;
+ wetsend[BACK_LEFT] = 0.0f;
+ wetsend[BACK_RIGHT] = 0.0f;
*wetgainhf = 1.0f;
}
+ wetsend[SIDE_LEFT] = 0.0f;
+ wetsend[SIDE_RIGHT] = 0.0f;
break;
default:
break;
@@ -479,16 +541,24 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
*wetgainhf = WetGainHF;
//1. Multi-channel buffers always play "normal"
- drysend[0] = SourceVolume * 1.0f * ListenerGain;
- drysend[1] = SourceVolume * 1.0f * ListenerGain;
- drysend[2] = SourceVolume * 1.0f * ListenerGain;
- drysend[3] = SourceVolume * 1.0f * ListenerGain;
+ 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;
if(ALSource->Send[0].Slot.effectslot)
{
- wetsend[0] = SourceVolume * 0.0f * ListenerGain;
- wetsend[1] = SourceVolume * 0.0f * ListenerGain;
- wetsend[2] = SourceVolume * 0.0f * ListenerGain;
- wetsend[3] = SourceVolume * 0.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;
+ wetsend[LFE] = SourceVolume * 0.0f * ListenerGain;
*wetgainhf = 1.0f;
}
@@ -500,8 +570,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 };
- ALfloat WetSend[OUTPUTCHANNELS] = { 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 };
ALfloat DryGainHF = 0.0f;
ALfloat WetGainHF = 0.0f;
ALuint BlockAlign,BufferSize;
@@ -631,33 +701,76 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
//Direct path final mix buffer and panning
value = aluComputeDrySample(ALSource, DryGainHF, sample);
- DryBuffer[j][0] += value*DrySend[0];
- DryBuffer[j][1] += value*DrySend[1];
- DryBuffer[j][2] += value*DrySend[2];
- DryBuffer[j][3] += value*DrySend[3];
-
+ DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT];
+ DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT];
+#if 0 /* FIXME: Re-enable when proper 6-channel spatialization is used */
+ DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT];
+ DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT];
+#endif
+ DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT];
+ DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT];
//Room path final mix buffer and panning
value = aluComputeWetSample(ALSource, WetGainHF, sample);
- WetBuffer[j][0] += value*WetSend[0];
- WetBuffer[j][1] += value*WetSend[1];
- WetBuffer[j][2] += value*WetSend[2];
- WetBuffer[j][3] += value*WetSend[3];
+ WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT];
+ WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT];
+#if 0 /* FIXME: Re-enable when proper 6-channel spatialization is used */
+ WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT];
+ WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT];
+#endif
+ WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT];
+ WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT];
}
else
{
- //First order interpolator (left)
- value = (ALfloat)((ALshort)(((Data[k*2 ]*((1L<<FRACTIONBITS)-fraction))+(Data[k*2+2]*(fraction)))>>FRACTIONBITS));
- //Direct path final mix buffer and panning (left)
- DryBuffer[j][0] += value*DrySend[0];
- //Room path final mix buffer and panning (left)
- WetBuffer[j][0] += value*WetSend[0];
-
- //First order interpolator (right)
- value = (ALfloat)((ALshort)(((Data[k*2+1]*((1L<<FRACTIONBITS)-fraction))+(Data[k*2+3]*(fraction)))>>FRACTIONBITS));
- //Direct path final mix buffer and panning (right)
- DryBuffer[j][1] += value*DrySend[1];
- //Room path final mix buffer and panning (right)
- WetBuffer[j][1] += value*WetSend[1];
+ //First order interpolator (front left)
+ value = (ALfloat)((ALshort)(((Data[k*Channels ]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels ]*(fraction)))>>FRACTIONBITS));
+ DryBuffer[j][FRONT_LEFT] += value*DrySend[FRONT_LEFT];
+ WetBuffer[j][FRONT_LEFT] += value*WetSend[FRONT_LEFT];
+ //First order interpolator (front right)
+ value = (ALfloat)((ALshort)(((Data[k*Channels+1]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+1]*(fraction)))>>FRACTIONBITS));
+ DryBuffer[j][FRONT_RIGHT] += value*DrySend[FRONT_RIGHT];
+ WetBuffer[j][FRONT_RIGHT] += value*WetSend[FRONT_RIGHT];
+ if(Channels >= 4)
+ {
+ int i = 2;
+ if(Channels >= 7)
+ {
+ //First order interpolator (side left)
+ value = (ALfloat)((ALshort)(((Data[k*Channels+2]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+2]*(fraction)))>>FRACTIONBITS));
+ DryBuffer[j][SIDE_LEFT] += value*DrySend[SIDE_LEFT];
+ WetBuffer[j][SIDE_LEFT] += value*WetSend[SIDE_LEFT];
+ //First order interpolator (side right)
+ value = (ALfloat)((ALshort)(((Data[k*Channels+3]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+3]*(fraction)))>>FRACTIONBITS));
+ DryBuffer[j][SIDE_RIGHT] += value*DrySend[SIDE_RIGHT];
+ WetBuffer[j][SIDE_RIGHT] += value*WetSend[SIDE_RIGHT];
+ i += 2;
+ }
+ //First order interpolator (back left)
+ value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
+ DryBuffer[j][BACK_LEFT] += value*DrySend[BACK_LEFT];
+ WetBuffer[j][BACK_LEFT] += value*WetSend[BACK_LEFT];
+ i++;
+ //First order interpolator (back right)
+ value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
+ DryBuffer[j][BACK_RIGHT] += value*DrySend[BACK_RIGHT];
+ WetBuffer[j][BACK_RIGHT] += value*WetSend[BACK_RIGHT];
+ i++;
+ if(Channels >= 6)
+ {
+ if(Channels != 7)
+ {
+ //First order interpolator (center)
+ value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
+ DryBuffer[j][CENTER] += value*DrySend[CENTER];
+ WetBuffer[j][CENTER] += value*WetSend[CENTER];
+ i++;
+ }
+ //First order interpolator (lfe)
+ value = (ALfloat)((ALshort)(((Data[k*Channels+i]*((1L<<FRACTIONBITS)-fraction))+(Data[(k+1)*Channels+i]*(fraction)))>>FRACTIONBITS));
+ DryBuffer[j][LFE] += value*DrySend[LFE];
+ WetBuffer[j][LFE] += value*WetSend[LFE];
+ }
+ }
}
DataPosFrac += increment;
j++;
@@ -751,46 +864,137 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
case AL_FORMAT_MONO8:
for(i = 0;i < SamplesToDo;i++)
{
- *((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1])>>8)+128);
+ ((ALubyte*)buffer)[0] = (ALubyte)((aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
+ WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT])>>8)+128);
buffer = ((ALubyte*)buffer) + 1;
}
break;
case AL_FORMAT_STEREO8:
- for(i = 0;i < SamplesToDo*2;i++)
+ for(i = 0;i < SamplesToDo;i++)
{
- *((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i>>1][i&1]+WetBuffer[i>>1][i&1])>>8)+128);
- buffer = ((ALubyte*)buffer) + 1;
+ ((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);
+ buffer = ((ALubyte*)buffer) + 2;
}
break;
case AL_FORMAT_QUAD8:
- for(i = 0;i < SamplesToDo*4;i++)
+ for(i = 0;i < SamplesToDo;i++)
{
- *((ALubyte*)buffer) = (ALubyte)((aluF2S(DryBuffer[i>>2][i&3]+WetBuffer[i>>2][i&3])>>8)+128);
- buffer = ((ALubyte*)buffer) + 1;
+ ((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][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
+ ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
+ buffer = ((ALubyte*)buffer) + 4;
+ }
+ break;
+ case AL_FORMAT_51CHN8:
+ 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][BACK_LEFT] +WetBuffer[i][BACK_LEFT])>>8)+128);
+ ((ALubyte*)buffer)[3] = (ALubyte)((aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT])>>8)+128);
+ ((ALubyte*)buffer)[4] = (ALubyte)((aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER])>>8)+128);
+ ((ALubyte*)buffer)[5] = (ALubyte)((aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE])>>8)+128);
+ 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++)
{
- *((ALshort*)buffer) = aluF2S(DryBuffer[i][0]+DryBuffer[i][1]+WetBuffer[i][0]+WetBuffer[i][1]);
+ ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT]+DryBuffer[i][FRONT_RIGHT]+
+ WetBuffer[i][FRONT_LEFT]+WetBuffer[i][FRONT_RIGHT]);
buffer = ((ALshort*)buffer) + 1;
}
break;
case AL_FORMAT_STEREO16:
- default:
- for(i = 0;i < SamplesToDo*2;i++)
+ for(i = 0;i < SamplesToDo;i++)
{
- *((ALshort*)buffer) = aluF2S(DryBuffer[i>>1][i&1]+WetBuffer[i>>1][i&1]);
- buffer = ((ALshort*)buffer) + 1;
+ ((ALshort*)buffer)[0] = aluF2S(DryBuffer[i][FRONT_LEFT] +WetBuffer[i][FRONT_LEFT]);
+ ((ALshort*)buffer)[1] = aluF2S(DryBuffer[i][FRONT_RIGHT]+WetBuffer[i][FRONT_RIGHT]);
+ buffer = ((ALshort*)buffer) + 2;
}
break;
case AL_FORMAT_QUAD16:
- for(i = 0;i < SamplesToDo*4;i++)
+ for(i = 0;i < SamplesToDo;i++)
{
- *((ALshort*)buffer) = aluF2S(DryBuffer[i>>2][i&3]+WetBuffer[i>>2][i&3]);
- buffer = ((ALshort*)buffer) + 1;
+ ((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][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
+ ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
+ buffer = ((ALshort*)buffer) + 4;
}
break;
+ case AL_FORMAT_51CHN16:
+ 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][BACK_LEFT] +WetBuffer[i][BACK_LEFT]);
+ ((ALshort*)buffer)[3] = aluF2S(DryBuffer[i][BACK_RIGHT] +WetBuffer[i][BACK_RIGHT]);
+ ((ALshort*)buffer)[4] = aluF2S(DryBuffer[i][CENTER] +WetBuffer[i][CENTER]);
+ ((ALshort*)buffer)[5] = aluF2S(DryBuffer[i][LFE] +WetBuffer[i][LFE]);
+ 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;
}
size -= SamplesToDo;
diff --git a/Alc/alsa.c b/Alc/alsa.c
index 2a46eff0..bef6ac99 100644
--- a/Alc/alsa.c
+++ b/Alc/alsa.c
@@ -36,6 +36,10 @@
typedef struct {
snd_pcm_t *pcmHandle;
snd_pcm_format_t format;
+
+ ALvoid *buffer;
+ ALsizei size;
+
int killNow;
ALvoid *thread;
} alsa_data;
@@ -63,6 +67,7 @@ MAKE_FUNC(snd_pcm_hw_params_set_rate_near);
MAKE_FUNC(snd_pcm_hw_params_set_rate);
MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near);
MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min);
+MAKE_FUNC(snd_pcm_hw_params_get_access);
MAKE_FUNC(snd_pcm_hw_params);
MAKE_FUNC(snd_pcm_prepare);
MAKE_FUNC(snd_pcm_start);
@@ -72,6 +77,7 @@ MAKE_FUNC(snd_pcm_avail_update);
MAKE_FUNC(snd_pcm_areas_silence);
MAKE_FUNC(snd_pcm_mmap_begin);
MAKE_FUNC(snd_pcm_mmap_commit);
+MAKE_FUNC(snd_pcm_writei);
MAKE_FUNC(snd_pcm_drain);
MAKE_FUNC(snd_pcm_info_malloc);
MAKE_FUNC(snd_pcm_info_free);
@@ -210,6 +216,76 @@ static ALuint ALSAProc(ALvoid *ptr)
return 0;
}
+static ALuint ALSANoMMapProc(ALvoid *ptr)
+{
+ ALCdevice *pDevice = (ALCdevice*)ptr;
+ alsa_data *data = (alsa_data*)pDevice->ExtraData;
+ snd_pcm_sframes_t avail;
+ char *WritePtr;
+ int err;
+
+ while(!data->killNow)
+ {
+ snd_pcm_state_t state = psnd_pcm_state(data->pcmHandle);
+ if(state == SND_PCM_STATE_XRUN)
+ {
+ err = xrun_recovery(data->pcmHandle, -EPIPE);
+ if (err < 0)
+ {
+ AL_PRINT("XRUN recovery failed: %s\n", psnd_strerror(err));
+ break;
+ }
+ }
+ else if (state == SND_PCM_STATE_SUSPENDED)
+ {
+ err = xrun_recovery(data->pcmHandle, -ESTRPIPE);
+ if (err < 0)
+ {
+ AL_PRINT("SUSPEND recovery failed: %s\n", psnd_strerror(err));
+ break;
+ }
+ }
+
+ SuspendContext(NULL);
+ aluMixData(pDevice->Context, data->buffer, data->size, pDevice->Format);
+ ProcessContext(NULL);
+
+ WritePtr = data->buffer;
+ avail = (snd_pcm_uframes_t)data->size / psnd_pcm_frames_to_bytes(data->pcmHandle, 1);
+ while(avail > 0)
+ {
+ int ret = psnd_pcm_writei(data->pcmHandle, WritePtr, avail);
+ switch (ret)
+ {
+ case -EAGAIN:
+ continue;
+ case -ESTRPIPE:
+ do {
+ ret = psnd_pcm_resume(data->pcmHandle);
+ } while(ret == -EAGAIN);
+ break;
+ case -EPIPE:
+ break;
+ default:
+ if (ret >= 0)
+ {
+ WritePtr += psnd_pcm_frames_to_bytes(data->pcmHandle, ret);
+ avail -= ret;
+ }
+ break;
+ }
+ if (ret < 0)
+ {
+ ret = psnd_pcm_prepare(data->pcmHandle);
+ if(ret < 0)
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
static void fill_silence(snd_pcm_t *pcmHandle, snd_pcm_format_t alsaFormat, int channels)
{
const snd_pcm_channel_area_t *areas = NULL;
@@ -263,13 +339,14 @@ static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceNam
{
snd_pcm_uframes_t bufferSizeInFrames;
snd_pcm_hw_params_t *p = NULL;
+ snd_pcm_access_t access;
unsigned int periods;
alsa_data *data;
char driver[64];
char *err;
int i;
- strncpy(driver, GetConfigValue("alsa", "default", "default"), sizeof(driver)-1);
+ strncpy(driver, GetConfigValue("alsa", "device", "default"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
if(deviceName)
{
@@ -324,16 +401,12 @@ open_alsa:
return ALC_FALSE;
}
- switch(device->Format)
+ switch(aluBytesFromFormat(device->Format))
{
- case AL_FORMAT_MONO8:
- case AL_FORMAT_STEREO8:
- case AL_FORMAT_QUAD8:
+ case 1:
data->format = SND_PCM_FORMAT_U8;
break;
- case AL_FORMAT_MONO16:
- case AL_FORMAT_STEREO16:
- case AL_FORMAT_QUAD16:
+ case 2:
data->format = SND_PCM_FORMAT_S16;
break;
default:
@@ -351,7 +424,8 @@ open_alsa:
/* start with the largest configuration space possible */
if(!(ok(psnd_pcm_hw_params_any(data->pcmHandle, p), "any") &&
/* set interleaved access */
- ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access") &&
+ (ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access") ||
+ ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED), "set access"))&&
/* set format (implicitly sets sample bits) */
ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, data->format), "set format") &&
/* set channels (implicitly sets frame bits) */
@@ -372,6 +446,16 @@ open_alsa:
return ALC_FALSE;
}
#undef ok
+
+ if((i=psnd_pcm_hw_params_get_access(p, &access)) < 0)
+ {
+ AL_PRINT("get_access failed: %s\n", psnd_strerror(i));
+ psnd_pcm_hw_params_free(p);
+ psnd_pcm_close(data->pcmHandle);
+ free(data);
+ return ALC_FALSE;
+ }
+
psnd_pcm_hw_params_free(p);
device->MaxNoOfSources = 256;
@@ -382,26 +466,46 @@ open_alsa:
{
AL_PRINT("prepare error: %s\n", psnd_strerror(i));
psnd_pcm_close(data->pcmHandle);
+ free(data->buffer);
free(data);
return ALC_FALSE;
}
- fill_silence(data->pcmHandle, data->format, device->Channels);
+ data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, bufferSizeInFrames);
+ if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
+ {
+ data->buffer = malloc(data->size);
+ if(!data->buffer)
+ {
+ AL_PRINT("buffer malloc failed\n");
+ psnd_pcm_close(data->pcmHandle);
+ free(data);
+ return ALC_FALSE;
+ }
+ }
+ else
+ fill_silence(data->pcmHandle, data->format, device->Channels);
+
i = psnd_pcm_start(data->pcmHandle);
if(i < 0)
{
AL_PRINT("start error: %s\n", psnd_strerror(i));
psnd_pcm_close(data->pcmHandle);
+ free(data->buffer);
free(data);
return ALC_FALSE;
}
device->ExtraData = data;
- data->thread = StartThread(ALSAProc, device);
+ if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
+ data->thread = StartThread(ALSANoMMapProc, device);
+ else
+ data->thread = StartThread(ALSAProc, device);
if(data->thread == NULL)
{
psnd_pcm_close(data->pcmHandle);
device->ExtraData = NULL;
+ free(data->buffer);
free(data);
return ALC_FALSE;
}
@@ -416,6 +520,7 @@ static void alsa_close_playback(ALCdevice *device)
StopThread(data->thread);
psnd_pcm_close(data->pcmHandle);
+ free(data->buffer);
free(data);
device->ExtraData = NULL;
}
@@ -690,6 +795,7 @@ LOAD_FUNC(snd_pcm_hw_params_set_rate_near);
LOAD_FUNC(snd_pcm_hw_params_set_rate);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min);
+LOAD_FUNC(snd_pcm_hw_params_get_access);
LOAD_FUNC(snd_pcm_hw_params);
LOAD_FUNC(snd_pcm_prepare);
LOAD_FUNC(snd_pcm_start);
@@ -699,6 +805,7 @@ LOAD_FUNC(snd_pcm_avail_update);
LOAD_FUNC(snd_pcm_areas_silence);
LOAD_FUNC(snd_pcm_mmap_begin);
LOAD_FUNC(snd_pcm_mmap_commit);
+LOAD_FUNC(snd_pcm_writei);
LOAD_FUNC(snd_pcm_drain);
LOAD_FUNC(snd_pcm_info_malloc);
diff --git a/Alc/dsound.c b/Alc/dsound.c
index a2b036a1..90a422a2 100644
--- a/Alc/dsound.c
+++ b/Alc/dsound.c
@@ -129,7 +129,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
memset(&OutputType, 0, sizeof(WAVEFORMATEX));
OutputType.wFormatTag = WAVE_FORMAT_PCM;
OutputType.nChannels = device->Channels;
- OutputType.wBitsPerSample = (((device->Format==AL_FORMAT_MONO16)||(device->Format==AL_FORMAT_STEREO16)||(device->Format==AL_FORMAT_QUAD16))?16:8);
+ OutputType.wBitsPerSample = aluBytesFromFormat(device->Format) * 8;
OutputType.nBlockAlign = OutputType.nChannels*OutputType.wBitsPerSample/8;
OutputType.nSamplesPerSec = device->Frequency;
OutputType.nAvgBytesPerSec = OutputType.nSamplesPerSec*OutputType.nBlockAlign;
diff --git a/Alc/oss.c b/Alc/oss.c
index de8f6e43..a63acb9b 100644
--- a/Alc/oss.c
+++ b/Alc/oss.c
@@ -174,17 +174,13 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
return ALC_FALSE;
}
- switch(device->Format)
+ switch(aluBytesFromFormat(device->Format))
{
- case AL_FORMAT_MONO8:
- case AL_FORMAT_STEREO8:
- case AL_FORMAT_QUAD8:
+ case 1:
data->silence = 0x80;
ossFormat = AFMT_U8;
break;
- case AL_FORMAT_MONO16:
- case AL_FORMAT_STEREO16:
- case AL_FORMAT_QUAD16:
+ case 2:
data->silence = 0;
ossFormat = AFMT_S16_NE;
break;
@@ -337,17 +333,13 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
return ALC_FALSE;
}
- switch(format)
+ switch(aluBytesFromFormat(format))
{
- case AL_FORMAT_MONO8:
- case AL_FORMAT_STEREO8:
- case AL_FORMAT_QUAD8:
+ case 1:
data->silence = 0x80;
ossFormat = AFMT_U8;
break;
- case AL_FORMAT_MONO16:
- case AL_FORMAT_STEREO16:
- case AL_FORMAT_QUAD16:
+ case 2:
data->silence = 0;
ossFormat = AFMT_S16_NE;
break;
diff --git a/CMakeLists.txt b/CMakeLists.txt
index df42e1f9..9bab5884 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -33,15 +33,6 @@ SET(LIB_BUILD_VERSION "38")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
-IF("${WIN32}")
- SET(LIBNAME openal32)
- SET(TARGET_OPTS "PREFIX \"\"")
-ELSE()
- SET(LIBNAME openal)
- SET(TARGET_OPTS "")
-ENDIF()
-
-
CHECK_TYPE_SIZE("long" SIZEOF_LONG)
CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
@@ -50,7 +41,6 @@ CHECK_TYPE_SIZE("void*" SIZEOF_VOIDP)
# Add definitions, compiler switches, etc.
INCLUDE_DIRECTORIES(OpenAL32/Include include "${OpenAL_BINARY_DIR}")
-SET(EXTRA_LIBS m ${EXTRA_LIBS})
IF("${MSVC}")
# ???
@@ -103,6 +93,9 @@ ELSEIF(NODEBUG)
ENDIF()
CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF)
+IF("${HAVE_SQRTF}")
+ SET(EXTRA_LIBS m ${EXTRA_LIBS})
+ENDIF()
CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
@@ -115,6 +108,16 @@ IF(NOT "${HAVE_STRCASECMP}")
ADD_DEFINITIONS(-Dstrcasecmp=_stricmp)
ENDIF()
+CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF)
+IF(NOT "${HAVE_SNPRINTF}")
+ CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF)
+ IF(NOT "${HAVE__SNPRINTF}")
+ MESSAGE(FATAL_ERROR "No snprintf function found, please report!")
+ ENDIF()
+
+ ADD_DEFINITIONS(-Dsnprintf=_snprintf)
+ENDIF()
+
# Check for the dlopen API (for dynamicly loading backend libs)
IF(DLOPEN)
CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H)
@@ -260,10 +263,18 @@ CONFIGURE_FILE(
ADD_DEFINITIONS(-DAL_BUILD_LIBRARY)
# Build a shared library
+IF("${WIN32}")
+ SET(LIBNAME openal32)
+ELSE()
+ SET(LIBNAME openal)
+ENDIF()
+
ADD_LIBRARY(${LIBNAME} SHARED ${OPENAL_OBJS} ${ALC_OBJS})
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION}
- SOVERSION ${LIB_MAJOR_VERSION}
- ${TARGET_OPTS})
+ SOVERSION ${LIB_MAJOR_VERSION})
+IF("${WIN32}")
+ SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
+ENDIF()
TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS})
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 168991b7..a5e5184a 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -1,9 +1,6 @@
#ifndef AL_MAIN_H
#define AL_MAIN_H
-#define AL_MAX_CHANNELS 4
-#define AL_MAX_SOURCES 32
-
#include <string.h>
#include "alu.h"
@@ -59,13 +56,7 @@ static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
#define max(x,y) (((x)>(y))?(x):(y))
#endif
-#include "alBuffer.h"
-#include "alError.h"
-#include "alExtension.h"
#include "alListener.h"
-#include "alSource.h"
-#include "alState.h"
-#include "alThunk.h"
#ifdef __cplusplus
extern "C"
@@ -82,20 +73,36 @@ extern char _alDebug[256];
if(!_al_print_fn) _al_print_fn = __FILE__; \
else _al_print_fn += 1; \
_al_print_i = snprintf(_alDebug, sizeof(_alDebug), "AL lib: %s:%d: ", _al_print_fn, __LINE__); \
- snprintf(_alDebug+_al_print_i, sizeof(_alDebug)-_al_print_i, __VA_ARGS__); \
+ if(_al_print_i < (int)sizeof(_alDebug) && _al_print_i > 0) \
+ snprintf(_alDebug+_al_print_i, sizeof(_alDebug)-_al_print_i, __VA_ARGS__); \
+ _alDebug[sizeof(_alDebug)-1] = 0; \
fprintf(stderr, "%s", _alDebug); \
} while(0)
+#define AL_FORMAT_MONO_FLOAT32 0x10010
+#define AL_FORMAT_STEREO_FLOAT32 0x10011
+
#define AL_FORMAT_MONO_IMA4 0x1300
#define AL_FORMAT_STEREO_IMA4 0x1301
-// These are from AL_EXT_MCFORMATS, which we don't support yet but the mixer
-// can use 4-channel formats
+
+#define AL_FORMAT_51CHN8 0x120A
+#define AL_FORMAT_51CHN16 0x120B
+#define AL_FORMAT_51CHN32 0x120C
+#define AL_FORMAT_61CHN8 0x120D
+#define AL_FORMAT_61CHN16 0x120E
+#define AL_FORMAT_61CHN32 0x120F
+#define AL_FORMAT_71CHN8 0x1210
+#define AL_FORMAT_71CHN16 0x1211
+#define AL_FORMAT_71CHN32 0x1212
#define AL_FORMAT_QUAD8 0x1204
#define AL_FORMAT_QUAD16 0x1205
+#define AL_FORMAT_QUAD32 0x1206
+#define AL_FORMAT_REAR8 0x1207
+#define AL_FORMAT_REAR16 0x1208
+#define AL_FORMAT_REAR32 0x1209
#define SWMIXER_OUTPUT_RATE 44100
-//#define OUTPUT_BUFFER_SIZE (32768*SWMIXER_OUTPUT_RATE/22050)
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
#define AIRABSORBGAINHF (0.994f)
@@ -154,8 +161,8 @@ struct ALCcontext_struct
{
ALlistener Listener;
- ALsource *Source;
- ALuint SourceCount;
+ struct ALsource *Source;
+ ALuint SourceCount;
ALenum LastError;
ALboolean InUse;
diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h
index f54d4721..09651fa5 100644
--- a/OpenAL32/Include/alSource.h
+++ b/OpenAL32/Include/alSource.h
@@ -31,7 +31,7 @@ typedef struct ALbufferlistitem
struct ALbufferlistitem *next;
} ALbufferlistitem;
-typedef struct ALsource_struct
+typedef struct ALsource
{
ALfloat flPitch;
ALfloat flGain;
@@ -94,7 +94,7 @@ typedef struct ALsource_struct
// Source Type (Static, Streaming, or Undetermined)
ALint lSourceType;
- struct ALsource_struct *next;
+ struct ALsource *next;
} ALsource;
#ifdef __cplusplus
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index e4fe0dc3..d43e0127 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -1,12 +1,6 @@
#ifndef _ALU_H_
#define _ALU_H_
-#define BUFFERSIZE 48000
-#define FRACTIONBITS 14
-#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
-#define MAX_PITCH 4
-#define OUTPUTCHANNELS 4
-
#include "AL/al.h"
#include "AL/alc.h"
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index 6b8a335c..282b8030 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -27,6 +27,8 @@
#include "alMain.h"
#include "alAuxEffectSlot.h"
+#include "alThunk.h"
+#include "alError.h"
static ALeffectslot *g_AuxiliaryEffectSlotList;
static ALuint g_AuxiliaryEffectSlotCount;
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c
index 0abdb61f..2bcb6562 100644
--- a/OpenAL32/alBuffer.c
+++ b/OpenAL32/alBuffer.c
@@ -27,8 +27,11 @@
#include "AL/alc.h"
#include "alError.h"
#include "alBuffer.h"
+#include "alThunk.h"
+static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat);
+
/*
* AL Buffer Functions
*
@@ -273,91 +276,143 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
switch(format)
{
case AL_FORMAT_MONO8:
- if ((size%1) == 0)
+ case AL_FORMAT_MONO16:
+ case AL_FORMAT_MONO_FLOAT32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16);
+ break;
+
+ case AL_FORMAT_STEREO8:
+ case AL_FORMAT_STEREO16:
+ case AL_FORMAT_STEREO_FLOAT32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16);
+ break;
+
+ case AL_FORMAT_REAR8:
+ case AL_FORMAT_REAR16:
+ case AL_FORMAT_REAR32: {
+ ALuint NewFormat = AL_FORMAT_QUAD16;
+ ALuint NewChannels = aluChannelsFromFormat(NewFormat);
+ ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 :
+ ((format==AL_FORMAT_REAR16) ? 2 :
+ 4));
+ ALsizei i;
+
+ assert(aluBytesFromFormat(NewFormat) == 2);
+
+ if ((size%(OrigBytes*2)) != 0)
{
- // 8bit Samples are converted to 16 bit here
- // Allocate 8 extra samples (16 bytes)
- ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALubyte))*(1*sizeof(ALshort)));
- if (ALBuf->data)
- {
- ALBuf->format = AL_FORMAT_MONO16;
- ALBuf->eOriginalFormat = AL_FORMAT_MONO8;
- for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++)
- ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8);
- memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 16);
- ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort);
- ALBuf->frequency=freq;
- }
- else
- alSetError(AL_OUT_OF_MEMORY);
- }
- else
alSetError(AL_INVALID_VALUE);
- break;
+ break;
+ }
- case AL_FORMAT_MONO16:
- if ((size%2) == 0)
+ switch(OrigBytes)
{
- // Allocate 8 extra samples (16 bytes)
- ALBuf->data=realloc(ALBuf->data,16+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
+ case 1:
+ size /= sizeof(ALubyte);
+ size *= 2;
+
+ // 8bit Samples are converted to 16 bit here
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
if (ALBuf->data)
{
- ALBuf->format = AL_FORMAT_MONO16;
- ALBuf->eOriginalFormat = AL_FORMAT_MONO16;
- memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort));
- memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 16);
- ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort);
- ALBuf->frequency=freq;
+ for (i = 0;i < size;i+=4)
+ {
+ ALBuf->data[i+0] = 0;
+ ALBuf->data[i+1] = 0;
+ ALBuf->data[i+2] = (ALshort)((((ALubyte*)data)[i/2+0]-128) << 8);
+ ALBuf->data[i+3] = (ALshort)((((ALubyte*)data)[i/2+1]-128) << 8);
+ }
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = format;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
}
else
alSetError(AL_OUT_OF_MEMORY);
- }
- else
- alSetError(AL_INVALID_VALUE);
- break;
+ break;
- case AL_FORMAT_STEREO8:
- if ((size%2) == 0)
- {
- // 8bit Samples are converted to 16 bit here
- // Allocate 8 extra samples (32 bytes)
- ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALubyte))*(1*sizeof(ALshort)));
+ case 2:
+ size /= sizeof(ALshort);
+ size *= 2;
+
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
if (ALBuf->data)
{
- ALBuf->format = AL_FORMAT_STEREO16;
- ALBuf->eOriginalFormat = AL_FORMAT_STEREO8;
- for (i=0;i<(ALsizei)(size/sizeof(ALubyte));i++)
- ALBuf->data[i]=(ALshort)((((ALubyte *)data)[i]-128)<<8);
- memset(&(ALBuf->data[size/sizeof(ALubyte)]), 0, 32);
- ALBuf->size=size/sizeof(ALubyte)*1*sizeof(ALshort);
- ALBuf->frequency=freq;
+ for (i = 0;i < size;i+=4)
+ {
+ ALBuf->data[i+0] = 0;
+ ALBuf->data[i+1] = 0;
+ ALBuf->data[i+2] = ((ALshort*)data)[i/2+0];
+ ALBuf->data[i+3] = ((ALshort*)data)[i/2+1];
+ }
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = format;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
}
else
alSetError(AL_OUT_OF_MEMORY);
- }
- else
- alSetError(AL_INVALID_VALUE);
- break;
+ break;
- case AL_FORMAT_STEREO16:
- if ((size%4) == 0)
- {
- // Allocate 8 extra samples (32 bytes)
- ALBuf->data=realloc(ALBuf->data,32+(size/sizeof(ALshort))*(1*sizeof(ALshort)));
+ case 4:
+ size /= sizeof(ALfloat);
+ size *= 2;
+
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
if (ALBuf->data)
{
- ALBuf->format = AL_FORMAT_STEREO16;
- ALBuf->eOriginalFormat = AL_FORMAT_STEREO16;
- memcpy(ALBuf->data,data,size/sizeof(ALshort)*1*sizeof(ALshort));
- memset(&(ALBuf->data[size/sizeof(ALshort)]), 0, 32);
- ALBuf->size=size/sizeof(ALshort)*1*sizeof(ALshort);
- ALBuf->frequency=freq;
+ for (i = 0;i < size;i+=4)
+ {
+ ALBuf->data[i+0] = 0;
+ ALBuf->data[i+1] = 0;
+ ALBuf->data[i+2] = (ALshort)(((ALfloat*)data)[i/2+0] * 32767.5f - 0.5);
+ ALBuf->data[i+3] = (ALshort)(((ALfloat*)data)[i/2+1] * 32767.5f - 0.5);
+ }
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = format;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
}
else
alSetError(AL_OUT_OF_MEMORY);
+ break;
+
+ default:
+ assert(0);
}
- else
- alSetError(AL_INVALID_VALUE);
+ } break;
+
+ case AL_FORMAT_QUAD8:
+ case AL_FORMAT_QUAD16:
+ case AL_FORMAT_QUAD32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_QUAD16);
+ break;
+
+ case AL_FORMAT_51CHN8:
+ case AL_FORMAT_51CHN16:
+ case AL_FORMAT_51CHN32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_51CHN16);
+ break;
+
+ case AL_FORMAT_61CHN8:
+ case AL_FORMAT_61CHN16:
+ case AL_FORMAT_61CHN32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_61CHN16);
+ break;
+
+ case AL_FORMAT_71CHN8:
+ case AL_FORMAT_71CHN16:
+ case AL_FORMAT_71CHN32:
+ LoadData(ALBuf, data, size, freq, format, AL_FORMAT_71CHN16);
break;
case AL_FORMAT_MONO_IMA4:
@@ -489,7 +544,7 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
else if (LeftIndex>88) LeftIndex=88;
ALBuf->data[i*2*65+j+k+2]=(short)LeftSample;
LeftIMACode>>=4;
-
+
RightSample+=((g_IMAStep_size[RightIndex]*g_IMACodeword_4[RightIMACode&15])/8);
RightIndex+=g_IMAIndex_adjust_4[RightIMACode&15];
if (RightSample<-32768) RightSample=-32768;
@@ -817,11 +872,11 @@ ALAPI ALvoid ALAPIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plValu
break;
case AL_BITS:
- *plValue= (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_STEREO8))?8:16);
+ *plValue = aluBytesFromFormat(pBuffer->format) * 8;
break;
case AL_CHANNELS:
- *plValue = (((pBuffer->format==AL_FORMAT_MONO8)||(pBuffer->format==AL_FORMAT_MONO16))?1:2);
+ *plValue = aluChannelsFromFormat(pBuffer->format);
break;
case AL_SIZE:
@@ -917,6 +972,97 @@ ALAPI void ALAPIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValue
ProcessContext(pContext);
}
+/*
+ * LoadData
+ *
+ * Loads the specified data into the buffer, using the specified formats.
+ * Currently, the new format must be 16-bit, and must have the same channel
+ * configuration as the original format. This does NOT handle compressed
+ * formats (eg. IMA4).
+ */
+static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat)
+{
+ ALuint NewChannels = aluChannelsFromFormat(NewFormat);
+ ALuint OrigBytes = aluBytesFromFormat(OrigFormat);
+ ALuint OrigChannels = aluChannelsFromFormat(OrigFormat);
+ ALsizei i;
+
+ assert(aluBytesFromFormat(NewFormat) == 2);
+ assert(NewChannels == OrigChannels);
+
+ if ((size%(OrigBytes*OrigChannels)) != 0)
+ {
+ alSetError(AL_INVALID_VALUE);
+ return;
+ }
+
+ switch(OrigBytes)
+ {
+ case 1:
+ size /= sizeof(ALubyte);
+
+ // 8bit Samples are converted to 16 bit here
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ for (i = 0;i < size;i++)
+ ALBuf->data[i] = (ALshort)((data[i]-128) << 8);
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = OrigFormat;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+
+ case 2:
+ size /= sizeof(ALshort);
+
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ memcpy(ALBuf->data, data, size*1*sizeof(ALshort));
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = OrigFormat;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+
+ case 4:
+ size /= sizeof(ALfloat);
+
+ // Allocate 8 extra samples
+ ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
+ if (ALBuf->data)
+ {
+ for (i = 0;i < size;i++)
+ ALBuf->data[i] = (ALshort)(((ALfloat*)data)[i] * 32767.5f - 0.5);
+ memset(&(ALBuf->data[size]), 0, 16*NewChannels);
+
+ ALBuf->format = NewFormat;
+ ALBuf->eOriginalFormat = OrigFormat;
+ ALBuf->size = size*1*sizeof(ALshort);
+ ALBuf->frequency = freq;
+ }
+ else
+ alSetError(AL_OUT_OF_MEMORY);
+ break;
+
+ default:
+ assert(0);
+ }
+}
+
/*
* ReleaseALBuffers()
diff --git a/OpenAL32/alEffect.c b/OpenAL32/alEffect.c
index 823d09ae..97778f9e 100644
--- a/OpenAL32/alEffect.c
+++ b/OpenAL32/alEffect.c
@@ -27,6 +27,8 @@
#include "alMain.h"
#include "alEffect.h"
+#include "alThunk.h"
+#include "alError.h"
static ALeffect *g_EffectList;
static ALuint g_EffectCount;
diff --git a/OpenAL32/alExtension.c b/OpenAL32/alExtension.c
index 54371ff4..fff46d0a 100644
--- a/OpenAL32/alExtension.c
+++ b/OpenAL32/alExtension.c
@@ -27,6 +27,7 @@
#include "alFilter.h"
#include "alEffect.h"
#include "alAuxEffectSlot.h"
+#include "alSource.h"
#include "AL/al.h"
#include "AL/alc.h"
@@ -202,12 +203,27 @@ static ALenums enumeration[]={
// Buffer Formats
{ (ALchar *)"AL_FORMAT_MONO8", AL_FORMAT_MONO8 },
{ (ALchar *)"AL_FORMAT_MONO16", AL_FORMAT_MONO16 },
+ { (ALchar *)"AL_FORMAT_MONO_FLOAT32", AL_FORMAT_MONO_FLOAT32 },
{ (ALchar *)"AL_FORMAT_STEREO8", AL_FORMAT_STEREO8 },
{ (ALchar *)"AL_FORMAT_STEREO16", AL_FORMAT_STEREO16 },
+ { (ALchar *)"AL_FORMAT_STEREO_FLOAT32", AL_FORMAT_STEREO_FLOAT32 },
{ (ALchar *)"AL_FORMAT_MONO_IMA4", AL_FORMAT_MONO_IMA4 },
{ (ALchar *)"AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 },
{ (ALchar *)"AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 },
{ (ALchar *)"AL_FORMAT_QUAD16", AL_FORMAT_QUAD16 },
+ { (ALchar *)"AL_FORMAT_QUAD32", AL_FORMAT_QUAD32 },
+ { (ALchar *)"AL_FORMAT_51CHN8", AL_FORMAT_51CHN8 },
+ { (ALchar *)"AL_FORMAT_51CHN16", AL_FORMAT_51CHN16 },
+ { (ALchar *)"AL_FORMAT_51CHN32", AL_FORMAT_51CHN32 },
+ { (ALchar *)"AL_FORMAT_61CHN8", AL_FORMAT_61CHN8 },
+ { (ALchar *)"AL_FORMAT_61CHN16", AL_FORMAT_61CHN16 },
+ { (ALchar *)"AL_FORMAT_61CHN32", AL_FORMAT_61CHN32 },
+ { (ALchar *)"AL_FORMAT_71CHN8", AL_FORMAT_71CHN8 },
+ { (ALchar *)"AL_FORMAT_71CHN16", AL_FORMAT_71CHN16 },
+ { (ALchar *)"AL_FORMAT_71CHN32", AL_FORMAT_71CHN32 },
+ { (ALchar *)"AL_FORMAT_REAR8", AL_FORMAT_REAR8 },
+ { (ALchar *)"AL_FORMAT_REAR16", AL_FORMAT_REAR16 },
+ { (ALchar *)"AL_FORMAT_REAR32", AL_FORMAT_REAR32 },
// Buffer attributes
{ (ALchar *)"AL_FREQUENCY", AL_FREQUENCY },
diff --git a/OpenAL32/alFilter.c b/OpenAL32/alFilter.c
index 80da100a..0753d799 100644
--- a/OpenAL32/alFilter.c
+++ b/OpenAL32/alFilter.c
@@ -27,6 +27,8 @@
#include "alMain.h"
#include "alFilter.h"
+#include "alThunk.h"
+#include "alError.h"
static ALfilter *g_FilterList;
static ALuint g_FilterCount;
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index 5b40f7eb..746ec821 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -26,6 +26,8 @@
#include "AL/alc.h"
#include "alError.h"
#include "alSource.h"
+#include "alBuffer.h"
+#include "alThunk.h"
static ALvoid InitSourceParams(ALsource *pSource);
static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset);
@@ -1983,6 +1985,7 @@ static ALvoid InitSourceParams(ALsource *pSource)
static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset)
{
ALbufferlistitem *pBufferList;
+ ALbuffer *pBuffer;
ALfloat flBufferFreq;
ALint lBytesPlayed, lChannels;
ALenum eOriginalFormat;
@@ -1991,10 +1994,11 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
if (((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED)) && (pSource->ulBufferID))
{
+ pBuffer = ALTHUNK_LOOKUPENTRY(pSource->ulBufferID);
// Get Current Buffer Size and frequency (in milliseconds)
- flBufferFreq = (ALfloat)(((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->frequency);
- eOriginalFormat = ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->eOriginalFormat;
- lChannels = ((((ALbuffer*)ALTHUNK_LOOKUPENTRY(pSource->ulBufferID))->format == AL_FORMAT_MONO16)?1:2);
+ flBufferFreq = (ALfloat)pBuffer->frequency;
+ eOriginalFormat = pBuffer->eOriginalFormat;
+ lChannels = aluChannelsFromFormat(pBuffer->format);
// Get Current BytesPlayed
lBytesPlayed = pSource->position * lChannels * 2; // NOTE : This is the byte offset into the *current* buffer
@@ -2041,17 +2045,30 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
break;
case AL_BYTE_OFFSET:
// Take into account the original format of the Buffer
- if ((eOriginalFormat == AL_FORMAT_MONO8) || (eOriginalFormat == AL_FORMAT_STEREO8))
- {
- *pflOffset = (ALfloat)(lBytesPlayed >> 1);
- }
- else if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) || (eOriginalFormat == AL_FORMAT_STEREO_IMA4))
+ if ((eOriginalFormat == AL_FORMAT_MONO_IMA4) ||
+ (eOriginalFormat == AL_FORMAT_STEREO_IMA4))
{
// Compression rate of the ADPCM supported is 3.6111 to 1
lBytesPlayed = (ALint)((ALfloat)lBytesPlayed / 3.6111f);
// Round down to nearest ADPCM block
*pflOffset = (ALfloat)((lBytesPlayed / (36 * lChannels)) * 36 * lChannels);
}
+ else if (eOriginalFormat == AL_FORMAT_REAR8)
+ {
+ *pflOffset = (ALfloat)(lBytesPlayed >> 2);
+ }
+ else if (eOriginalFormat == AL_FORMAT_REAR16)
+ {
+ *pflOffset = (ALfloat)(lBytesPlayed >> 1);
+ }
+ else if (aluBytesFromFormat(eOriginalFormat) == 1)
+ {
+ *pflOffset = (ALfloat)(lBytesPlayed >> 1);
+ }
+ else if (aluBytesFromFormat(eOriginalFormat) == 4)
+ {
+ *pflOffset = (ALfloat)(lBytesPlayed << 1);
+ }
else
{
*pflOffset = (ALfloat)lBytesPlayed;
@@ -2077,6 +2094,7 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext)
{
ALbufferlistitem *pBufferList;
+ ALbuffer *pBuffer;
ALint lBufferSize, lTotalBufferSize;
ALint lByteOffset;
@@ -2093,7 +2111,8 @@ static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext)
pSource->BuffersProcessed = 0;
while (pBufferList)
{
- lBufferSize = pBufferList->buffer ? ((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->size : 0;
+ pBuffer = ALTHUNK_LOOKUPENTRY(pBufferList->buffer);
+ lBufferSize = pBuffer ? pBuffer->size : 0;
if ((lTotalBufferSize + lBufferSize) <= lByteOffset)
{
@@ -2122,7 +2141,9 @@ static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext)
pSource->lBytesPlayed = lByteOffset;
// SW Mixer Positions are in Samples
- pSource->position = pSource->BufferPosition / ((((ALbuffer*)ALTHUNK_LOOKUPENTRY(pBufferList->buffer))->format == AL_FORMAT_MONO16)?2:4);
+ pSource->position = pSource->BufferPosition /
+ aluBytesFromFormat(pBuffer->format) /
+ aluChannelsFromFormat(pBuffer->format);
}
else
{
@@ -2179,19 +2200,15 @@ static ALint GetByteOffset(ALsource *pSource)
if (pBuffer)
{
flBufferFreq = ((ALfloat)pBuffer->frequency);
- lChannels = (pBuffer->format == AL_FORMAT_MONO16)?1:2;
+ lChannels = aluChannelsFromFormat(pBuffer->format);
// Determine the ByteOffset (and ensure it is block aligned)
switch (pSource->lOffsetType)
{
case AL_BYTE_OFFSET:
// Take into consideration the original format
- if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO8) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO8))
- {
- lByteOffset = pSource->lOffset * 2;
- lByteOffset -= (lByteOffset % (lChannels * 2));
- }
- else if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) || (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4))
+ if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) ||
+ (pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4))
{
// Round down to nearest ADPCM block
lByteOffset = (pSource->lOffset / (36 * lChannels)) * 36 * lChannels;
@@ -2199,6 +2216,26 @@ static ALint GetByteOffset(ALsource *pSource)
lByteOffset = (ALint)(3.6111f * (ALfloat)lByteOffset);
lByteOffset -= (lByteOffset % (lChannels * 2));
}
+ else if (pBuffer->eOriginalFormat == AL_FORMAT_REAR8)
+ {
+ lByteOffset = pSource->lOffset * 4;
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ else if (pBuffer->eOriginalFormat == AL_FORMAT_REAR16)
+ {
+ lByteOffset = pSource->lOffset * 2;
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ else if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 1)
+ {
+ lByteOffset = pSource->lOffset * 2;
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
+ else if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 4)
+ {
+ lByteOffset = pSource->lOffset / 2;
+ lByteOffset -= (lByteOffset % (lChannels * 2));
+ }
else
{
lByteOffset = pSource->lOffset;
diff --git a/openalrc.sample b/openalrc.sample
index ca6fe390..cb4b28dc 100644
--- a/openalrc.sample
+++ b/openalrc.sample
@@ -12,9 +12,15 @@ format = AL_FORMAT_STEREO16 # Sets the output format. Can be one of:
# AL_FORMAT_MONO8 (8-bit mono)
# 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