Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f1414c650e | |||
| 869b041f2f | |||
| 8621fbb015 | |||
| 597e01153e | |||
| d3e5fcd13e | |||
| 3e0f9cc716 | |||
| c7e49c9f57 | |||
| e2ed8ff2bf | |||
| 559c786d0c | |||
| c3a7480961 | |||
| a75e75aef5 | |||
| d45b1207d0 | |||
| 5a9e24dea1 | |||
| dc8132e965 | |||
| 20bcdc1ef6 | |||
| 93c0f61050 | |||
| 3a8c543f8b | |||
| 9e96156451 | |||
| 19aabd6d02 | |||
| 87b5d7bc7b | |||
| 646714b585 | |||
| eba60c30c5 | |||
| e66bb09156 | |||
| 0042b1f80d | |||
| 6d416ee734 | |||
| 97d3a45aff | |||
| 9e9ff44b17 | |||
| f369be148f | |||
| 3a09e446b3 | |||
| 2d0b12e49e | |||
| 55e2f294ac | |||
| 2a4b467f08 | |||
| 2ae9da696a | |||
| 376997c3ef |
@@ -33,6 +33,7 @@
|
||||
#include "AL/alc.h"
|
||||
#include "alThunk.h"
|
||||
#include "alSource.h"
|
||||
#include "alBuffer.h"
|
||||
#include "alExtension.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "bs2b.h"
|
||||
@@ -182,6 +183,8 @@ static ALCint alcEFXMinorVersion = 0;
|
||||
static ALCdevice *g_pDeviceList = NULL;
|
||||
static ALCuint g_ulDeviceCount = 0;
|
||||
|
||||
static CRITICAL_SECTION g_csMutex;
|
||||
|
||||
// Context List
|
||||
static ALCcontext *g_pContextList = NULL;
|
||||
static ALCuint g_ulContextCount = 0;
|
||||
@@ -189,23 +192,69 @@ static ALCuint g_ulContextCount = 0;
|
||||
// Context Error
|
||||
static ALCenum g_eLastContextError = ALC_NO_ERROR;
|
||||
|
||||
static ALboolean init_done = AL_FALSE;
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// ALC Related helper functions
|
||||
#ifdef _WIN32
|
||||
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
|
||||
{
|
||||
(void)lpReserved;
|
||||
|
||||
// Perform actions based on the reason for calling.
|
||||
switch(ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
DisableThreadLibraryCalls(hModule);
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
if(!init_done)
|
||||
break;
|
||||
ReleaseALC();
|
||||
ReleaseALBuffers();
|
||||
ReleaseALEffects();
|
||||
ReleaseALFilters();
|
||||
FreeALConfig();
|
||||
ALTHUNK_EXIT();
|
||||
DeleteCriticalSection(&g_csMutex);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
#ifdef HAVE_GCC_DESTRUCTOR
|
||||
static void my_deinit() __attribute__((destructor));
|
||||
static void my_deinit()
|
||||
{
|
||||
static ALenum once = AL_FALSE;
|
||||
if(once || !init_done) return;
|
||||
once = AL_TRUE;
|
||||
|
||||
ReleaseALC();
|
||||
ReleaseALBuffers();
|
||||
ReleaseALEffects();
|
||||
ReleaseALFilters();
|
||||
FreeALConfig();
|
||||
ALTHUNK_EXIT();
|
||||
DeleteCriticalSection(&g_csMutex);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void InitAL(void)
|
||||
{
|
||||
static int done = 0;
|
||||
if(!done)
|
||||
if(!init_done)
|
||||
{
|
||||
int i;
|
||||
const char *devs, *str;
|
||||
|
||||
done = 1;
|
||||
init_done = AL_TRUE;
|
||||
|
||||
InitializeCriticalSection(&_alMutex);
|
||||
InitializeCriticalSection(&g_csMutex);
|
||||
ALTHUNK_INIT();
|
||||
ReadALConfig();
|
||||
|
||||
@@ -335,7 +384,7 @@ ALCvoid SetALCError(ALenum errorCode)
|
||||
ALCvoid SuspendContext(ALCcontext *pContext)
|
||||
{
|
||||
(void)pContext;
|
||||
EnterCriticalSection(&_alMutex);
|
||||
EnterCriticalSection(&g_csMutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -347,7 +396,7 @@ ALCvoid SuspendContext(ALCcontext *pContext)
|
||||
ALCvoid ProcessContext(ALCcontext *pContext)
|
||||
{
|
||||
(void)pContext;
|
||||
LeaveCriticalSection(&_alMutex);
|
||||
LeaveCriticalSection(&g_csMutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -392,7 +441,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_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET AL_LOKI_quadriphonic");
|
||||
pContext->ExtensionList = "AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET AL_LOKI_quadriphonic";
|
||||
|
||||
level = GetConfigValueInt(NULL, "cf_level", 0);
|
||||
if(level > 0 && level <= 6)
|
||||
@@ -1169,9 +1218,9 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
|
||||
if(!aluChannelsFromFormat(device->Format))
|
||||
device->Format = AL_FORMAT_STEREO16;
|
||||
|
||||
device->UpdateSize = GetConfigValueInt(NULL, "refresh", 8192);
|
||||
device->UpdateSize = GetConfigValueInt(NULL, "refresh", 4096);
|
||||
if((ALint)device->UpdateSize <= 0)
|
||||
device->UpdateSize = 8192;
|
||||
device->UpdateSize = 4096;
|
||||
|
||||
device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
|
||||
if((ALint)device->MaxNoOfSources <= 0)
|
||||
@@ -1230,7 +1279,12 @@ ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
|
||||
ProcessContext(NULL);
|
||||
|
||||
if(pDevice->Context)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
AL_PRINT("alcCloseDevice(): destroying 1 Context\n");
|
||||
#endif
|
||||
alcDestroyContext(pDevice->Context);
|
||||
}
|
||||
ALCdevice_ClosePlayback(pDevice);
|
||||
|
||||
//Release device structure
|
||||
@@ -1248,11 +1302,9 @@ ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
|
||||
|
||||
ALCvoid ReleaseALC(ALCvoid)
|
||||
{
|
||||
InitAL();
|
||||
|
||||
#ifdef _DEBUG
|
||||
if(g_ulContextCount > 0)
|
||||
AL_PRINT("exit() %u device(s) and %u context(s) NOT deleted\n", g_ulDeviceCount, g_ulContextCount);
|
||||
if(g_ulDeviceCount > 0)
|
||||
AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
|
||||
#endif
|
||||
|
||||
while(g_pDeviceList)
|
||||
|
||||
@@ -64,7 +64,7 @@ typedef long long ALint64;
|
||||
#define __min min
|
||||
#endif
|
||||
|
||||
#define BUFFERSIZE 48000
|
||||
#define BUFFERSIZE 24000
|
||||
#define FRACTIONBITS 14
|
||||
#define FRACTIONMASK ((1L<<FRACTIONBITS)-1)
|
||||
#define MAX_PITCH 4
|
||||
@@ -163,6 +163,42 @@ __inline ALuint aluChannelsFromFormat(ALenum format)
|
||||
}
|
||||
|
||||
|
||||
static __inline ALfloat lpFilter(FILTER *iir, ALfloat input)
|
||||
{
|
||||
unsigned int i;
|
||||
float *hist1_ptr,*hist2_ptr,*coef_ptr;
|
||||
ALfloat output,new_hist,history1,history2;
|
||||
|
||||
coef_ptr = iir->coef; /* coefficient pointer */
|
||||
|
||||
hist1_ptr = iir->history; /* first history */
|
||||
hist2_ptr = hist1_ptr + 1; /* next history */
|
||||
|
||||
/* 1st number of coefficients array is overall input scale factor,
|
||||
* or filter gain */
|
||||
output = input * (*coef_ptr++);
|
||||
|
||||
for(i = 0;i < FILTER_SECTIONS;i++)
|
||||
{
|
||||
history1 = *hist1_ptr; /* history values */
|
||||
history2 = *hist2_ptr;
|
||||
|
||||
output = output - history1 * (*coef_ptr++);
|
||||
new_hist = output - history2 * (*coef_ptr++); /* poles */
|
||||
|
||||
output = new_hist + history1 * (*coef_ptr++);
|
||||
output = output + history2 * (*coef_ptr++); /* zeros */
|
||||
|
||||
*hist2_ptr++ = *hist1_ptr;
|
||||
*hist1_ptr++ = new_hist;
|
||||
hist1_ptr++;
|
||||
hist2_ptr++;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
static __inline ALshort aluF2S(ALfloat Value)
|
||||
{
|
||||
ALint i;
|
||||
@@ -210,20 +246,9 @@ static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat matrix[3][3])
|
||||
memcpy(vector, result, sizeof(result));
|
||||
}
|
||||
|
||||
static __inline ALfloat aluComputeSample(ALfloat GainHF, ALfloat sample, ALfloat LastSample)
|
||||
static __inline ALfloat aluComputeSample(ALfloat GainHF, ALfloat sample, ALfloat LowSample)
|
||||
{
|
||||
if(GainHF < 1.0f)
|
||||
{
|
||||
if(GainHF > 0.0f)
|
||||
{
|
||||
sample *= GainHF;
|
||||
sample += LastSample * (1.0f-GainHF);
|
||||
}
|
||||
else
|
||||
sample = 0.0f;
|
||||
}
|
||||
|
||||
return sample;
|
||||
return LowSample + ((sample - LowSample) * GainHF);
|
||||
}
|
||||
|
||||
static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
@@ -247,7 +272,7 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
ALfloat WetGainHF = 1.0f;
|
||||
|
||||
//Get context properties
|
||||
DopplerFactor = ALContext->DopplerFactor;
|
||||
DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
|
||||
DopplerVelocity = ALContext->DopplerVelocity;
|
||||
flSpeedOfSound = ALContext->flSpeedOfSound;
|
||||
|
||||
@@ -273,6 +298,10 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
if(isMono != AL_FALSE)
|
||||
{
|
||||
//1. Translate Listener to origin (convert to head relative)
|
||||
// Note that Direction and SourceToListener are *not* transformed.
|
||||
// SourceToListener is used with the source and listener velocities,
|
||||
// which are untransformed, and Direction is used with SourceToListener
|
||||
// for the sound cone
|
||||
if(ALSource->bHeadRelative==AL_FALSE)
|
||||
{
|
||||
// Build transform matrix
|
||||
@@ -290,10 +319,21 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
Position[0] -= ALContext->Listener.Position[0];
|
||||
Position[1] -= ALContext->Listener.Position[1];
|
||||
Position[2] -= ALContext->Listener.Position[2];
|
||||
|
||||
SourceToListener[0] = -Position[0];
|
||||
SourceToListener[1] = -Position[1];
|
||||
SourceToListener[2] = -Position[2];
|
||||
|
||||
// Transform source position and direction into listener space
|
||||
aluMatrixVector(Position, Matrix);
|
||||
aluMatrixVector(Direction, Matrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
SourceToListener[0] = -Position[0];
|
||||
SourceToListener[1] = -Position[1];
|
||||
SourceToListener[2] = -Position[2];
|
||||
}
|
||||
aluNormalize(SourceToListener);
|
||||
aluNormalize(Direction);
|
||||
|
||||
//2. Calculate distance attenuation
|
||||
@@ -302,7 +342,7 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
if(ALSource->Send[0].Slot && !ALSource->Send[0].Slot->AuxSendAuto)
|
||||
{
|
||||
if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
|
||||
RoomRolloff = ALSource->Send[0].Slot->effect.Reverb.RoomRolloffFactor;
|
||||
RoomRolloff += ALSource->Send[0].Slot->effect.Reverb.RoomRolloffFactor;
|
||||
}
|
||||
|
||||
flAttenuation = 1.0f;
|
||||
@@ -372,11 +412,6 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
WetMix = __max(WetMix,MinVolume);
|
||||
|
||||
//3. Apply directional soundcones
|
||||
SourceToListener[0] = -Position[0];
|
||||
SourceToListener[1] = -Position[1];
|
||||
SourceToListener[2] = -Position[2];
|
||||
aluNormalize(SourceToListener);
|
||||
|
||||
Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * 180.0f /
|
||||
3.141592654f;
|
||||
if(Angle >= InnerAngle && Angle <= OuterAngle)
|
||||
@@ -458,6 +493,7 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
|
||||
if(ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB)
|
||||
{
|
||||
WetMix *= ALSource->Send[0].Slot->effect.Reverb.Gain;
|
||||
WetGainHF *= ALSource->Send[0].Slot->effect.Reverb.GainHF;
|
||||
WetGainHF *= pow(ALSource->Send[0].Slot->effect.Reverb.AirAbsorptionGainHF,
|
||||
Distance * MetersPerUnit);
|
||||
@@ -477,17 +513,20 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
switch(aluChannelsFromFormat(OutputFormat))
|
||||
{
|
||||
case 1:
|
||||
drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f); //Direct
|
||||
drysend[FRONT_RIGHT] = DryMix * aluSqrt(1.0f); //Direct
|
||||
wetsend[FRONT_LEFT] = WetMix * aluSqrt(1.0f); //Room
|
||||
wetsend[FRONT_RIGHT] = WetMix * aluSqrt(1.0f); //Room
|
||||
break;
|
||||
case 2:
|
||||
PanningLR = 0.5f + 0.5f*Position[0];
|
||||
drysend[FRONT_LEFT] = DryMix * aluSqrt(1.0f-PanningLR); //L Direct
|
||||
drysend[FRONT_RIGHT] = DryMix * aluSqrt( PanningLR); //R Direct
|
||||
drysend[BACK_LEFT] = drysend[FRONT_LEFT];
|
||||
drysend[BACK_RIGHT] = drysend[FRONT_RIGHT];
|
||||
drysend[SIDE_LEFT] = drysend[FRONT_LEFT];
|
||||
drysend[SIDE_RIGHT] = drysend[FRONT_RIGHT];
|
||||
wetsend[FRONT_LEFT] = WetMix * aluSqrt(1.0f-PanningLR); //L Room
|
||||
wetsend[FRONT_RIGHT] = WetMix * aluSqrt( PanningLR); //R Room
|
||||
wetsend[BACK_LEFT] = wetsend[FRONT_LEFT];
|
||||
wetsend[BACK_RIGHT] = wetsend[FRONT_RIGHT];
|
||||
wetsend[SIDE_LEFT] = wetsend[FRONT_LEFT];
|
||||
wetsend[SIDE_RIGHT] = wetsend[FRONT_RIGHT];
|
||||
break;
|
||||
case 4:
|
||||
/* TODO: Add center/lfe channel in spatial calculations? */
|
||||
@@ -503,10 +542,14 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
|
||||
drysend[FRONT_RIGHT] = DryMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
||||
drysend[BACK_LEFT] = DryMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
||||
drysend[BACK_RIGHT] = DryMix * aluSqrt(( PanningLR)*( PanningFB));
|
||||
drysend[SIDE_LEFT] = (drysend[FRONT_LEFT] +drysend[BACK_LEFT]) * 0.5f;
|
||||
drysend[SIDE_RIGHT] = (drysend[FRONT_RIGHT]+drysend[BACK_RIGHT]) * 0.5f;
|
||||
wetsend[FRONT_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*(1.0f-PanningFB));
|
||||
wetsend[FRONT_RIGHT] = WetMix * aluSqrt(( PanningLR)*(1.0f-PanningFB));
|
||||
wetsend[BACK_LEFT] = WetMix * aluSqrt((1.0f-PanningLR)*( PanningFB));
|
||||
wetsend[BACK_RIGHT] = WetMix * aluSqrt(( PanningLR)*( PanningFB));
|
||||
wetsend[SIDE_LEFT] = (wetsend[FRONT_LEFT] +wetsend[BACK_LEFT]) * 0.5f;
|
||||
wetsend[SIDE_RIGHT] = (wetsend[FRONT_RIGHT]+wetsend[BACK_RIGHT]) * 0.5f;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
@@ -585,7 +628,6 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
{
|
||||
static float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
|
||||
static float WetBuffer[BUFFERSIZE][OUTPUTCHANNELS];
|
||||
static float ReverbBuffer[BUFFERSIZE];
|
||||
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;
|
||||
@@ -593,11 +635,10 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
ALuint BlockAlign,BufferSize;
|
||||
ALuint DataSize=0,DataPosInt=0,DataPosFrac=0;
|
||||
ALuint Channels,Frequency,ulExtraSamples;
|
||||
ALfloat DrySample, WetSample;
|
||||
ALboolean doReverb;
|
||||
ALfloat Pitch;
|
||||
ALint Looping,increment,State;
|
||||
ALuint Buffer,fraction;
|
||||
ALint Looping,State;
|
||||
ALint fraction,increment;
|
||||
ALuint Buffer;
|
||||
ALuint SamplesToDo;
|
||||
ALsource *ALSource;
|
||||
ALbuffer *ALBuffer;
|
||||
@@ -608,6 +649,7 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
ALbufferlistitem *BufferListItem;
|
||||
ALuint loop;
|
||||
ALint64 DataSize64,DataPos64;
|
||||
FILTER *Filter;
|
||||
|
||||
SuspendContext(ALContext);
|
||||
|
||||
@@ -626,7 +668,6 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
//Clear mixing buffer
|
||||
memset(DryBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
|
||||
memset(WetBuffer, 0, SamplesToDo*OUTPUTCHANNELS*sizeof(ALfloat));
|
||||
memset(ReverbBuffer, 0, SamplesToDo*sizeof(ALfloat));
|
||||
|
||||
//Actual mixing loop
|
||||
while(ALSource)
|
||||
@@ -634,10 +675,6 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
j = 0;
|
||||
State = ALSource->state;
|
||||
|
||||
doReverb = ((ALSource->Send[0].Slot &&
|
||||
ALSource->Send[0].Slot->effect.type == AL_EFFECT_REVERB) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
|
||||
while(State == AL_PLAYING && j < SamplesToDo)
|
||||
{
|
||||
DataSize = 0;
|
||||
@@ -666,8 +703,7 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
//Get source info
|
||||
DataPosInt = ALSource->position;
|
||||
DataPosFrac = ALSource->position_fraction;
|
||||
DrySample = ALSource->LastDrySample;
|
||||
WetSample = ALSource->LastWetSample;
|
||||
Filter = &ALSource->iirFilter;
|
||||
|
||||
//Compute 18.14 fixed point step
|
||||
increment = (ALint)(Pitch*(ALfloat)(1L<<FRACTIONBITS));
|
||||
@@ -675,13 +711,13 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
increment = (MAX_PITCH<<FRACTIONBITS);
|
||||
|
||||
//Figure out how many samples we can mix.
|
||||
//Pitch must be <= 4 (the number below !)
|
||||
DataSize64 = DataSize+MAX_PITCH;
|
||||
DataSize64 = DataSize;
|
||||
DataSize64 <<= FRACTIONBITS;
|
||||
DataPos64 = DataPosInt;
|
||||
DataPos64 <<= FRACTIONBITS;
|
||||
DataPos64 += DataPosFrac;
|
||||
BufferSize = (ALuint)((DataSize64-DataPos64) / increment);
|
||||
BufferSize = (ALuint)((DataSize64-DataPos64+(increment-1)) / increment);
|
||||
|
||||
BufferListItem = ALSource->queue;
|
||||
for(loop = 0; loop < ALSource->BuffersPlayed; loop++)
|
||||
{
|
||||
@@ -695,7 +731,7 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(BufferListItem->next->buffer);
|
||||
if(NextBuf && NextBuf->data)
|
||||
{
|
||||
ulExtraSamples = min(NextBuf->size, (ALint)(16*Channels));
|
||||
ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
|
||||
memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
|
||||
}
|
||||
}
|
||||
@@ -704,7 +740,7 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
ALbuffer *NextBuf = (ALbuffer*)ALTHUNK_LOOKUPENTRY(ALSource->queue->buffer);
|
||||
if (NextBuf && NextBuf->data)
|
||||
{
|
||||
ulExtraSamples = min(NextBuf->size, (ALint)(16*Channels));
|
||||
ulExtraSamples = min(NextBuf->size, (ALint)(ALBuffer->padding*Channels*2));
|
||||
memcpy(&Data[DataSize*Channels], NextBuf->data, ulExtraSamples);
|
||||
}
|
||||
}
|
||||
@@ -717,32 +753,31 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
{
|
||||
k = DataPosFrac>>FRACTIONBITS;
|
||||
fraction = DataPosFrac&FRACTIONMASK;
|
||||
|
||||
if(Channels==1)
|
||||
{
|
||||
ALfloat sample, lowsamp, outsamp;
|
||||
//First order interpolator
|
||||
ALfloat sample = (ALfloat)((ALshort)(((Data[k]*((1L<<FRACTIONBITS)-fraction))+(Data[k+1]*(fraction)))>>FRACTIONBITS));
|
||||
sample = (Data[k]*((1<<FRACTIONBITS)-fraction) +
|
||||
Data[k+1]*fraction) >> FRACTIONBITS;
|
||||
lowsamp = lpFilter(Filter, sample);
|
||||
|
||||
//Direct path final mix buffer and panning
|
||||
DrySample = aluComputeSample(DryGainHF, sample, DrySample);
|
||||
DryBuffer[j][FRONT_LEFT] += DrySample*DrySend[FRONT_LEFT];
|
||||
DryBuffer[j][FRONT_RIGHT] += DrySample*DrySend[FRONT_RIGHT];
|
||||
DryBuffer[j][SIDE_LEFT] += DrySample*DrySend[SIDE_LEFT];
|
||||
DryBuffer[j][SIDE_RIGHT] += DrySample*DrySend[SIDE_RIGHT];
|
||||
DryBuffer[j][BACK_LEFT] += DrySample*DrySend[BACK_LEFT];
|
||||
DryBuffer[j][BACK_RIGHT] += DrySample*DrySend[BACK_RIGHT];
|
||||
outsamp = aluComputeSample(DryGainHF, sample, lowsamp);
|
||||
DryBuffer[j][FRONT_LEFT] += outsamp*DrySend[FRONT_LEFT];
|
||||
DryBuffer[j][FRONT_RIGHT] += outsamp*DrySend[FRONT_RIGHT];
|
||||
DryBuffer[j][SIDE_LEFT] += outsamp*DrySend[SIDE_LEFT];
|
||||
DryBuffer[j][SIDE_RIGHT] += outsamp*DrySend[SIDE_RIGHT];
|
||||
DryBuffer[j][BACK_LEFT] += outsamp*DrySend[BACK_LEFT];
|
||||
DryBuffer[j][BACK_RIGHT] += outsamp*DrySend[BACK_RIGHT];
|
||||
//Room path final mix buffer and panning
|
||||
WetSample = aluComputeSample(WetGainHF, sample, WetSample);
|
||||
if(doReverb)
|
||||
ReverbBuffer[j] += WetSample;
|
||||
else
|
||||
{
|
||||
WetBuffer[j][FRONT_LEFT] += WetSample*WetSend[FRONT_LEFT];
|
||||
WetBuffer[j][FRONT_RIGHT] += WetSample*WetSend[FRONT_RIGHT];
|
||||
WetBuffer[j][SIDE_LEFT] += WetSample*WetSend[SIDE_LEFT];
|
||||
WetBuffer[j][SIDE_RIGHT] += WetSample*WetSend[SIDE_RIGHT];
|
||||
WetBuffer[j][BACK_LEFT] += WetSample*WetSend[BACK_LEFT];
|
||||
WetBuffer[j][BACK_RIGHT] += WetSample*WetSend[BACK_RIGHT];
|
||||
}
|
||||
outsamp = aluComputeSample(WetGainHF, sample, lowsamp);
|
||||
WetBuffer[j][FRONT_LEFT] += outsamp*WetSend[FRONT_LEFT];
|
||||
WetBuffer[j][FRONT_RIGHT] += outsamp*WetSend[FRONT_RIGHT];
|
||||
WetBuffer[j][SIDE_LEFT] += outsamp*WetSend[SIDE_LEFT];
|
||||
WetBuffer[j][SIDE_RIGHT] += outsamp*WetSend[SIDE_RIGHT];
|
||||
WetBuffer[j][BACK_LEFT] += outsamp*WetSend[BACK_LEFT];
|
||||
WetBuffer[j][BACK_RIGHT] += outsamp*WetSend[BACK_RIGHT];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -816,8 +851,6 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
//Update source info
|
||||
ALSource->position = DataPosInt;
|
||||
ALSource->position_fraction = DataPosFrac;
|
||||
ALSource->LastDrySample = DrySample;
|
||||
ALSource->LastWetSample = WetSample;
|
||||
}
|
||||
|
||||
//Handle looping sources
|
||||
@@ -907,27 +940,26 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
ALuint Length = ALEffectSlot->ReverbLength;
|
||||
ALfloat DecayGain = ALEffectSlot->ReverbDecayGain;
|
||||
ALfloat DecayHFRatio = ALEffectSlot->effect.Reverb.DecayHFRatio;
|
||||
ALfloat Gain = ALEffectSlot->effect.Reverb.Gain;
|
||||
ALfloat ReflectGain = ALEffectSlot->effect.Reverb.ReflectionsGain;
|
||||
ALfloat LateReverbGain = ALEffectSlot->effect.Reverb.LateReverbGain;
|
||||
ALfloat LastDecaySample = ALEffectSlot->LastDecaySample;
|
||||
ALfloat sample;
|
||||
ALfloat sample, lowsample;
|
||||
|
||||
Filter = &ALEffectSlot->iirFilter;
|
||||
for(i = 0;i < SamplesToDo;i++)
|
||||
{
|
||||
DelayBuffer[Pos] = ReverbBuffer[i] * Gain;
|
||||
sample = WetBuffer[i][FRONT_LEFT] +WetBuffer[i][SIDE_LEFT] +WetBuffer[i][BACK_LEFT];
|
||||
sample += WetBuffer[i][FRONT_RIGHT]+WetBuffer[i][SIDE_RIGHT]+WetBuffer[i][BACK_RIGHT];
|
||||
DelayBuffer[Pos] = sample / 6.0f;
|
||||
|
||||
sample = DelayBuffer[ReflectPos] * ReflectGain;
|
||||
|
||||
DelayBuffer[LatePos] *= LateReverbGain;
|
||||
|
||||
Pos = (Pos+1) % Length;
|
||||
DelayBuffer[Pos] *= DecayHFRatio;
|
||||
DelayBuffer[Pos] += LastDecaySample * (1.0f-DecayHFRatio);
|
||||
LastDecaySample = DelayBuffer[Pos];
|
||||
DelayBuffer[Pos] *= DecayGain;
|
||||
lowsample = lpFilter(Filter, DelayBuffer[Pos]);
|
||||
lowsample += (DelayBuffer[Pos]-lowsample) * DecayHFRatio;
|
||||
|
||||
DelayBuffer[LatePos] += DelayBuffer[Pos];
|
||||
DelayBuffer[LatePos] += lowsample * DecayGain;
|
||||
|
||||
sample += DelayBuffer[LatePos];
|
||||
|
||||
@@ -945,7 +977,6 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
|
||||
ALEffectSlot->ReverbPos = Pos;
|
||||
ALEffectSlot->ReverbLatePos = LatePos;
|
||||
ALEffectSlot->ReverbReflectPos = ReflectPos;
|
||||
ALEffectSlot->LastDecaySample = LastDecaySample;
|
||||
}
|
||||
|
||||
ALEffectSlot = ALEffectSlot->next;
|
||||
|
||||
+9
-8
@@ -83,22 +83,21 @@ ALuint StopThread(ALvoid *thread)
|
||||
typedef struct {
|
||||
ALuint (*func)(ALvoid*);
|
||||
ALvoid *ptr;
|
||||
ALuint ret;
|
||||
pthread_t thread;
|
||||
} ThreadInfo;
|
||||
|
||||
static void *StarterFunc(void *ptr)
|
||||
{
|
||||
ThreadInfo *inf = (ThreadInfo*)ptr;
|
||||
ALint ret;
|
||||
|
||||
ret = inf->func(inf->ptr);
|
||||
return (void*)ret;
|
||||
inf->ret = inf->func(inf->ptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
|
||||
{
|
||||
ThreadInfo *inf = malloc(sizeof(ThreadInfo));
|
||||
if(!inf) return 0;
|
||||
if(!inf) return NULL;
|
||||
|
||||
inf->func = func;
|
||||
inf->ptr = ptr;
|
||||
@@ -114,12 +113,14 @@ ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr)
|
||||
ALuint StopThread(ALvoid *thread)
|
||||
{
|
||||
ThreadInfo *inf = thread;
|
||||
void *ret;
|
||||
ALuint ret;
|
||||
|
||||
pthread_join(inf->thread, NULL);
|
||||
ret = inf->ret;
|
||||
|
||||
pthread_join(inf->thread, &ret);
|
||||
free(inf);
|
||||
|
||||
return (ALuint)ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ typedef struct {
|
||||
ALvoid *buffer;
|
||||
ALsizei size;
|
||||
|
||||
int killNow;
|
||||
volatile int killNow;
|
||||
ALvoid *thread;
|
||||
} alsa_data;
|
||||
|
||||
|
||||
+2
-2
@@ -48,7 +48,7 @@ typedef struct {
|
||||
LPDIRECTSOUNDBUFFER DSpbuffer;
|
||||
LPDIRECTSOUNDBUFFER DSsbuffer;
|
||||
|
||||
int killNow;
|
||||
volatile int killNow;
|
||||
ALvoid *thread;
|
||||
} DSoundData;
|
||||
|
||||
@@ -173,7 +173,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
if(*(GetConfigValue(NULL, "format", "")) != 0)
|
||||
if(*(GetConfigValue(NULL, "format", "")) == 0)
|
||||
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
|
||||
else
|
||||
{
|
||||
|
||||
+458
@@ -0,0 +1,458 @@
|
||||
/* ----------------- file filterIIR00.c begin ----------------- */
|
||||
/*
|
||||
Resonant low pass filter source code.
|
||||
By baltrax@hotmail.com (Zxform)
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alFilter.h"
|
||||
|
||||
|
||||
static void szxform(
|
||||
double *a0, double *a1, double *a2, /* numerator coefficients */
|
||||
double *b0, double *b1, double *b2, /* denominator coefficients */
|
||||
double fc, /* Filter cutoff frequency */
|
||||
double fs, /* sampling rate */
|
||||
double *k, /* overall gain factor */
|
||||
float *coef); /* pointer to 4 iir coefficients */
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
*
|
||||
* lpFilter - Perform IIR filtering sample by sample on floats
|
||||
*
|
||||
* Implements cascaded direct form II second order sections.
|
||||
* Requires FILTER structure for history and coefficients.
|
||||
* The size of the history array is 2*FILTER_SECTIONS.
|
||||
* The size of the coefficient array is 4*FILTER_SECTIONS + 1 because
|
||||
* the first coefficient is the overall scale factor for the filter.
|
||||
* Returns one output sample for each input sample.
|
||||
*
|
||||
* float lpFilter(FILTER *iir,float input)
|
||||
*
|
||||
* FILTER *iir pointer to FILTER structure
|
||||
* float input new float input sample
|
||||
*
|
||||
* Returns float value giving the current output.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*** moved to ALu.c ***/
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
*
|
||||
* InitLowPassFilter()
|
||||
*
|
||||
* Initialize filter coefficients.
|
||||
* We create a 4th order filter (24 db/oct rolloff), consisting
|
||||
* of two second order sections.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
int InitLowPassFilter(ALCcontext *Context, FILTER *iir)
|
||||
{
|
||||
float *coef;
|
||||
double fs, fc; /* Sampling frequency, cutoff frequency */
|
||||
double Q; /* Resonance > 1.0 < 1000 */
|
||||
unsigned nInd;
|
||||
double a0, a1, a2, b0, b1, b2;
|
||||
double k; /* overall gain factor */
|
||||
struct {
|
||||
double a0, a1, a2; /* numerator coefficients */
|
||||
double b0, b1, b2; /* denominator coefficients */
|
||||
} ProtoCoef[FILTER_SECTIONS]; /* Filter prototype coefficients,
|
||||
1 for each filter section */
|
||||
|
||||
|
||||
/*
|
||||
* Setup filter s-domain coefficients
|
||||
*/
|
||||
/* Section 1 */
|
||||
ProtoCoef[0].a0 = 1.0;
|
||||
ProtoCoef[0].a1 = 0;
|
||||
ProtoCoef[0].a2 = 0;
|
||||
ProtoCoef[0].b0 = 1.0;
|
||||
ProtoCoef[0].b1 = 0.765367;
|
||||
ProtoCoef[0].b2 = 1.0;
|
||||
|
||||
/* Section 2 */
|
||||
ProtoCoef[1].a0 = 1.0;
|
||||
ProtoCoef[1].a1 = 0;
|
||||
ProtoCoef[1].a2 = 0;
|
||||
ProtoCoef[1].b0 = 1.0;
|
||||
ProtoCoef[1].b1 = 1.847759;
|
||||
ProtoCoef[1].b2 = 1.0;
|
||||
|
||||
/* Clear the coefficient and history arrays */
|
||||
memset(iir->coef, 0, sizeof(iir->coef));
|
||||
memset(iir->history, 0, sizeof(iir->history));
|
||||
|
||||
k = 1.0; /* Set overall filter gain */
|
||||
coef = iir->coef + 1; /* Skip k, or gain */
|
||||
|
||||
Q = 1; /* Resonance */
|
||||
fc = LOWPASSFREQCUTOFF; /* Filter cutoff (Hz) */
|
||||
fs = Context->Frequency; /* Sampling frequency (Hz) */
|
||||
|
||||
/*
|
||||
* Compute z-domain coefficients for each biquad section
|
||||
* for new Cutoff Frequency and Resonance
|
||||
*/
|
||||
for (nInd = 0; nInd < FILTER_SECTIONS; nInd++)
|
||||
{
|
||||
a0 = ProtoCoef[nInd].a0;
|
||||
a1 = ProtoCoef[nInd].a1;
|
||||
a2 = ProtoCoef[nInd].a2;
|
||||
|
||||
b0 = ProtoCoef[nInd].b0;
|
||||
b1 = ProtoCoef[nInd].b1 / Q; /* Divide by resonance or Q */
|
||||
b2 = ProtoCoef[nInd].b2;
|
||||
szxform(&a0, &a1, &a2, &b0, &b1, &b2, fc, fs, &k, coef);
|
||||
coef += 4; /* Point to next filter section */
|
||||
}
|
||||
|
||||
/* Update overall filter gain in coef array */
|
||||
iir->coef[0] = k;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ----------------- file filterIIR00.c end ----------------- */
|
||||
|
||||
|
||||
/* ----------------- file bilinear.c begin ----------------- */
|
||||
/*
|
||||
* ----------------------------------------------------------
|
||||
* bilinear.c
|
||||
*
|
||||
* Perform bilinear transformation on s-domain coefficients
|
||||
* of 2nd order biquad section.
|
||||
* First design an analog filter and use s-domain coefficients
|
||||
* as input to szxform() to convert them to z-domain.
|
||||
*
|
||||
* Here's the butterworth polinomials for 2nd, 4th and 6th order sections.
|
||||
* When we construct a 24 db/oct filter, we take to 2nd order
|
||||
* sections and compute the coefficients separately for each section.
|
||||
*
|
||||
* n Polinomials
|
||||
* --------------------------------------------------------------------
|
||||
* 2 s^2 + 1.4142s +1
|
||||
* 4 (s^2 + 0.765367s + 1) (s^2 + 1.847759s + 1)
|
||||
* 6 (s^2 + 0.5176387s + 1) (s^2 + 1.414214 + 1) (s^2 + 1.931852s + 1)
|
||||
*
|
||||
* Where n is a filter order.
|
||||
* For n=4, or two second order sections, we have following equasions for each
|
||||
* 2nd order stage:
|
||||
*
|
||||
* (1 / (s^2 + (1/Q) * 0.765367s + 1)) * (1 / (s^2 + (1/Q) * 1.847759s + 1))
|
||||
*
|
||||
* Where Q is filter quality factor in the range of
|
||||
* 1 to 1000. The overall filter Q is a product of all
|
||||
* 2nd order stages. For example, the 6th order filter
|
||||
* (3 stages, or biquads) with individual Q of 2 will
|
||||
* have filter Q = 2 * 2 * 2 = 8.
|
||||
*
|
||||
* The nominator part is just 1.
|
||||
* The denominator coefficients for stage 1 of filter are:
|
||||
* b2 = 1; b1 = 0.765367; b0 = 1;
|
||||
* numerator is
|
||||
* a2 = 0; a1 = 0; a0 = 1;
|
||||
*
|
||||
* The denominator coefficients for stage 1 of filter are:
|
||||
* b2 = 1; b1 = 1.847759; b0 = 1;
|
||||
* numerator is
|
||||
* a2 = 0; a1 = 0; a0 = 1;
|
||||
*
|
||||
* These coefficients are used directly by the szxform()
|
||||
* and bilinear() functions. For all stages the numerator
|
||||
* is the same and the only thing that is different between
|
||||
* different stages is 1st order coefficient. The rest of
|
||||
* coefficients are the same for any stage and equal to 1.
|
||||
*
|
||||
* Any filter could be constructed using this approach.
|
||||
*
|
||||
* References:
|
||||
* Van Valkenburg, "Analog Filter Design"
|
||||
* Oxford University Press 1982
|
||||
* ISBN 0-19-510734-9
|
||||
*
|
||||
* C Language Algorithms for Digital Signal Processing
|
||||
* Paul Embree, Bruce Kimble
|
||||
* Prentice Hall, 1991
|
||||
* ISBN 0-13-133406-9
|
||||
*
|
||||
* Digital Filter Designer's Handbook
|
||||
* With C++ Algorithms
|
||||
* Britton Rorabaugh
|
||||
* McGraw Hill, 1997
|
||||
* ISBN 0-07-053806-9
|
||||
* ----------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void prewarp(double *a0, double *a1, double *a2, double fc, double fs);
|
||||
static void bilinear(
|
||||
double a0, double a1, double a2, /* numerator coefficients */
|
||||
double b0, double b1, double b2, /* denominator coefficients */
|
||||
double *k, /* overall gain factor */
|
||||
double fs, /* sampling rate */
|
||||
float *coef); /* pointer to 4 iir coefficients */
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------
|
||||
* Pre-warp the coefficients of a numerator or denominator.
|
||||
* Note that a0 is assumed to be 1, so there is no wrapping
|
||||
* of it.
|
||||
* ----------------------------------------------------------
|
||||
*/
|
||||
static void prewarp(
|
||||
double *a0, double *a1, double *a2,
|
||||
double fc, double fs)
|
||||
{
|
||||
double wp, pi;
|
||||
|
||||
pi = 4.0 * atan(1.0);
|
||||
wp = 2.0 * fs * tan(pi * fc / fs);
|
||||
|
||||
*a2 = (*a2) / (wp * wp);
|
||||
*a1 = (*a1) / wp;
|
||||
(void)a0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------
|
||||
* bilinear()
|
||||
*
|
||||
* Transform the numerator and denominator coefficients
|
||||
* of s-domain biquad section into corresponding
|
||||
* z-domain coefficients.
|
||||
*
|
||||
* Store the 4 IIR coefficients in array pointed by coef
|
||||
* in following order:
|
||||
* beta1, beta2 (denominator)
|
||||
* alpha1, alpha2 (numerator)
|
||||
*
|
||||
* Arguments:
|
||||
* a0-a2 - s-domain numerator coefficients
|
||||
* b0-b2 - s-domain denominator coefficients
|
||||
* k - filter gain factor. initially set to 1
|
||||
* and modified by each biquad section in such
|
||||
* a way, as to make it the coefficient by
|
||||
* which to multiply the overall filter gain
|
||||
* in order to achieve a desired overall filter gain,
|
||||
* specified in initial value of k.
|
||||
* fs - sampling rate (Hz)
|
||||
* coef - array of z-domain coefficients to be filled in.
|
||||
*
|
||||
* Return:
|
||||
* On return, set coef z-domain coefficients
|
||||
* ----------------------------------------------------------
|
||||
*/
|
||||
static void bilinear(
|
||||
double a0, double a1, double a2, /* numerator coefficients */
|
||||
double b0, double b1, double b2, /* denominator coefficients */
|
||||
double *k, /* overall gain factor */
|
||||
double fs, /* sampling rate */
|
||||
float *coef /* pointer to 4 iir coefficients */
|
||||
)
|
||||
{
|
||||
double ad, bd;
|
||||
|
||||
/* alpha (Numerator in s-domain) */
|
||||
ad = 4. * a2 * fs * fs + 2. * a1 * fs + a0;
|
||||
/* beta (Denominator in s-domain) */
|
||||
bd = 4. * b2 * fs * fs + 2. * b1* fs + b0;
|
||||
|
||||
/* update gain constant for this section */
|
||||
*k *= ad/bd;
|
||||
|
||||
/* Denominator */
|
||||
*coef++ = (2.*b0 - 8.*b2*fs*fs) / bd; /* beta1 */
|
||||
*coef++ = (4.*b2*fs*fs - 2.*b1*fs + b0) / bd; /* beta2 */
|
||||
|
||||
/* Nominator */
|
||||
*coef++ = (2.*a0 - 8.*a2*fs*fs) / ad; /* alpha1 */
|
||||
*coef = (4.*a2*fs*fs - 2.*a1*fs + a0) / ad; /* alpha2 */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------
|
||||
* Transform from s to z domain using bilinear transform
|
||||
* with prewarp.
|
||||
*
|
||||
* Arguments:
|
||||
* For argument description look at bilinear()
|
||||
*
|
||||
* coef - pointer to array of floating point coefficients,
|
||||
* corresponding to output of bilinear transofrm
|
||||
* (z domain).
|
||||
*
|
||||
* Note: frequencies are in Hz.
|
||||
* ----------------------------------------------------------
|
||||
*/
|
||||
static void szxform(
|
||||
double *a0, double *a1, double *a2, /* numerator coefficients */
|
||||
double *b0, double *b1, double *b2, /* denominator coefficients */
|
||||
double fc, /* Filter cutoff frequency */
|
||||
double fs, /* sampling rate */
|
||||
double *k, /* overall gain factor */
|
||||
float *coef) /* pointer to 4 iir coefficients */
|
||||
{
|
||||
/* Calculate a1 and a2 and overwrite the original values */
|
||||
prewarp(a0, a1, a2, fc, fs);
|
||||
prewarp(b0, b1, b2, fc, fs);
|
||||
bilinear(*a0, *a1, *a2, *b0, *b1, *b2, k, fs, coef);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------- file bilinear.c end ----------------- */
|
||||
|
||||
/* ----------------- file filter.txt begin -----------------
|
||||
How to construct a kewl low pass resonant filter?
|
||||
|
||||
Lets assume we want to create a filter for analog synth.
|
||||
The filter rolloff is 24 db/oct, which corresponds to 4th
|
||||
order filter. Filter of first order is equivalent to RC circuit
|
||||
and has max rolloff of 6 db/oct.
|
||||
|
||||
We will use classical Butterworth IIR filter design, as it
|
||||
exactly corresponds to our requirements.
|
||||
|
||||
A common practice is to chain several 2nd order sections,
|
||||
or biquads, as they commonly called, in order to achive a higher
|
||||
order filter. Each 2nd order section is a 2nd order filter, which
|
||||
has 12 db/oct roloff. So, we need 2 of those sections in series.
|
||||
|
||||
To compute those sections, we use standard Butterworth polinomials,
|
||||
or so called s-domain representation and convert it into z-domain,
|
||||
or digital domain. The reason we need to do this is because
|
||||
the filter theory exists for analog filters for a long time
|
||||
and there exist no theory of working in digital domain directly.
|
||||
So the common practice is to take standard analog filter design
|
||||
and use so called bilinear transform to convert the butterworth
|
||||
equasion coefficients into z-domain.
|
||||
|
||||
Once we compute the z-domain coefficients, we can use them in
|
||||
a very simple transfer function, such as iir_filter() in our
|
||||
C source code, in order to perform the filtering function.
|
||||
The filter itself is the simpliest thing in the world.
|
||||
The most complicated thing is computing the coefficients
|
||||
for z-domain.
|
||||
|
||||
Ok, lets look at butterworth polynomials, arranged as a series
|
||||
of 2nd order sections:
|
||||
|
||||
* Note: n is filter order.
|
||||
*
|
||||
* n Polynomials
|
||||
* --------------------------------------------------------------------
|
||||
* 2 s^2 + 1.4142s +1
|
||||
* 4 (s^2 + 0.765367s + 1) * (s^2 + 1.847759s + 1)
|
||||
* 6 (s^2 + 0.5176387s + 1) * (s^2 + 1.414214 + 1) * (s^2 + 1.931852s + 1)
|
||||
*
|
||||
* For n=4 we have following equasion for the filter transfer function:
|
||||
*
|
||||
* 1 1
|
||||
* T(s) = --------------------------- * ----------------------------
|
||||
* s^2 + (1/Q) * 0.765367s + 1 s^2 + (1/Q) * 1.847759s + 1
|
||||
*
|
||||
|
||||
The filter consists of two 2nd order secions since highest s power is 2.
|
||||
Now we can take the coefficients, or the numbers by which s is multiplied
|
||||
and plug them into a standard formula to be used by bilinear transform.
|
||||
|
||||
Our standard form for each 2nd order secion is:
|
||||
|
||||
a2 * s^2 + a1 * s + a0
|
||||
H(s) = ----------------------
|
||||
b2 * s^2 + b1 * s + b0
|
||||
|
||||
Note that butterworth nominator is 1 for all filter sections,
|
||||
which means s^2 = 0 and s^1 = 0
|
||||
|
||||
Lets convert standard butterworth polinomials into this form:
|
||||
|
||||
0 + 0 + 1 0 + 0 + 1
|
||||
-------------------------- * --------------------------
|
||||
1 + ((1/Q) * 0.765367) + 1 1 + ((1/Q) * 1.847759) + 1
|
||||
|
||||
Section 1:
|
||||
a2 = 0; a1 = 0; a0 = 1;
|
||||
b2 = 1; b1 = 0.5176387; b0 = 1;
|
||||
|
||||
Section 2:
|
||||
a2 = 0; a1 = 0; a0 = 1;
|
||||
b2 = 1; b1 = 1.847759; b0 = 1;
|
||||
|
||||
That Q is filter quality factor or resonance, in the range of
|
||||
1 to 1000. The overall filter Q is a product of all 2nd order stages.
|
||||
For example, the 6th order filter (3 stages, or biquads)
|
||||
with individual Q of 2 will have filter Q = 2 * 2 * 2 = 8.
|
||||
|
||||
These a and b coefficients are used directly by the szxform()
|
||||
and bilinear() functions.
|
||||
|
||||
The transfer function for z-domain is:
|
||||
|
||||
1 + alpha1 * z^(-1) + alpha2 * z^(-2)
|
||||
H(z) = -------------------------------------
|
||||
1 + beta1 * z^(-1) + beta2 * z^(-2)
|
||||
|
||||
When you need to change the filter frequency cutoff or resonance,
|
||||
or Q, you call the szxform() function with proper a and b
|
||||
coefficients and the new filter cutoff frequency or resonance.
|
||||
You also need to supply the sampling rate and filter gain you want
|
||||
to achive. For our purposes the gain = 1.
|
||||
|
||||
We call szxform() function 2 times becase we have 2 filter sections.
|
||||
Each call provides different coefficients.
|
||||
|
||||
The gain argument to szxform() is a pointer to desired filter
|
||||
gain variable.
|
||||
|
||||
double k = 1.0; // overall gain factor
|
||||
|
||||
Upon return from each call, the k argument will be set to a value,
|
||||
by which to multiply our actual signal in order for the gain
|
||||
to be one. On second call to szxform() we provide k that was
|
||||
changed by the previous section. During actual audio filtering
|
||||
function iir_filter() will use this k
|
||||
|
||||
Summary:
|
||||
|
||||
Our filter is pretty close to ideal in terms of all relevant
|
||||
parameters and filter stability even with extremely large values
|
||||
of resonance. This filter design has been verified under all
|
||||
variations of parameters and it all appears to work as advertized.
|
||||
|
||||
Good luck with it.
|
||||
If you ever make a directX wrapper for it, post it to comp.dsp.
|
||||
|
||||
|
||||
*
|
||||
* ----------------------------------------------------------
|
||||
*References:
|
||||
*Van Valkenburg, "Analog Filter Design"
|
||||
*Oxford University Press 1982
|
||||
*ISBN 0-19-510734-9
|
||||
*
|
||||
*C Language Algorithms for Digital Signal Processing
|
||||
*Paul Embree, Bruce Kimble
|
||||
*Prentice Hall, 1991
|
||||
*ISBN 0-13-133406-9
|
||||
*
|
||||
*Digital Filter Designer's Handbook
|
||||
*With C++ Algorithms
|
||||
*Britton Rorabaugh
|
||||
*McGraw Hill, 1997
|
||||
*ISBN 0-07-053806-9
|
||||
* ----------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// ----------------- file filter.txt end ----------------- */
|
||||
@@ -52,7 +52,7 @@ static char *oss_device_capture;
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
int killNow;
|
||||
volatile int killNow;
|
||||
ALvoid *thread;
|
||||
|
||||
ALubyte *mix_data;
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ typedef struct {
|
||||
ALvoid *buffer;
|
||||
ALuint size;
|
||||
|
||||
int killNow;
|
||||
volatile int killNow;
|
||||
ALvoid *thread;
|
||||
} wave_data;
|
||||
|
||||
|
||||
+43
-14
@@ -1,5 +1,11 @@
|
||||
# CMake build file list for OpenAL
|
||||
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
|
||||
|
||||
IF(COMMAND CMAKE_POLICY)
|
||||
CMAKE_POLICY(SET CMP0003 NEW)
|
||||
ENDIF(COMMAND CMAKE_POLICY)
|
||||
|
||||
INCLUDE(CheckFunctionExists)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckIncludeFile)
|
||||
@@ -9,7 +15,7 @@ INCLUDE(CheckCSourceCompiles)
|
||||
INCLUDE(CheckTypeSize)
|
||||
|
||||
|
||||
PROJECT(OpenAL)
|
||||
PROJECT(OpenAL C)
|
||||
|
||||
|
||||
SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
|
||||
@@ -27,10 +33,19 @@ OPTION(WERROR "Treat compile warnings as errors" OFF)
|
||||
OPTION(EXAMPLES "Build example programs" ON)
|
||||
|
||||
|
||||
IF(WIN32)
|
||||
SET(LIBNAME openal32)
|
||||
ELSE()
|
||||
SET(LIBNAME openal)
|
||||
ENDIF()
|
||||
|
||||
SET(LIB_MAJOR_VERSION "1")
|
||||
SET(LIB_MINOR_VERSION "4")
|
||||
SET(LIB_BUILD_VERSION "270")
|
||||
SET(LIB_MINOR_VERSION "5")
|
||||
SET(LIB_BUILD_VERSION "304")
|
||||
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
|
||||
IF(NOT DEFINED LIB_INSTALL_DIR)
|
||||
SET(LIB_INSTALL_DIR "lib")
|
||||
ENDIF(NOT DEFINED LIB_INSTALL_DIR)
|
||||
|
||||
|
||||
CHECK_TYPE_SIZE("long" SIZEOF_LONG)
|
||||
@@ -203,7 +218,6 @@ SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
|
||||
OpenAL32/alSource.c
|
||||
OpenAL32/alState.c
|
||||
OpenAL32/alThunk.c
|
||||
OpenAL32/OpenAL32.c
|
||||
)
|
||||
SET(ALC_OBJS Alc/ALc.c
|
||||
Alc/ALu.c
|
||||
@@ -211,6 +225,7 @@ SET(ALC_OBJS Alc/ALc.c
|
||||
Alc/alcRing.c
|
||||
Alc/alcThread.c
|
||||
Alc/bs2b.c
|
||||
Alc/lpfilter.c
|
||||
Alc/wave.c
|
||||
)
|
||||
|
||||
@@ -283,20 +298,26 @@ ENDIF()
|
||||
# This is always available
|
||||
SET(BACKENDS "${BACKENDS} WaveFile")
|
||||
|
||||
# Needed for openal.pc.in
|
||||
SET(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET(exec_prefix "\${prefix}")
|
||||
SET(libdir "\${exec_prefix}/${LIB_INSTALL_DIR}")
|
||||
SET(bindir "\${exec_prefix}/bin")
|
||||
SET(includedir "\${prefix}/include")
|
||||
SET(PACKAGE_VERSION "${LIB_VERSION}")
|
||||
|
||||
# End configuration
|
||||
CONFIGURE_FILE(
|
||||
"${OpenAL_SOURCE_DIR}/config.h.in"
|
||||
"${OpenAL_BINARY_DIR}/config.h")
|
||||
CONFIGURE_FILE(
|
||||
"${OpenAL_SOURCE_DIR}/admin/pkgconfig/openal.pc.in"
|
||||
"${OpenAL_BINARY_DIR}/admin/pkgconfig/openal.pc"
|
||||
@ONLY)
|
||||
|
||||
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})
|
||||
@@ -309,22 +330,24 @@ TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS})
|
||||
# Add an install target here
|
||||
INSTALL(TARGETS ${LIBNAME}
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
)
|
||||
INSTALL(FILES include/AL/al.h
|
||||
include/AL/alc.h
|
||||
include/AL/alext.h
|
||||
DESTINATION include/AL
|
||||
)
|
||||
INSTALL(FILES "${OpenAL_BINARY_DIR}/admin/pkgconfig/openal.pc"
|
||||
DESTINATION lib/pkgconfig)
|
||||
|
||||
IF(EXAMPLES)
|
||||
ADD_EXECUTABLE(openal-info examples/openal-info.c)
|
||||
TARGET_LINK_LIBRARIES(openal-info ${LIBNAME})
|
||||
INSTALL(TARGETS openal-info
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
||||
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
@@ -332,3 +355,9 @@ MESSAGE(STATUS "")
|
||||
MESSAGE(STATUS "Building OpenAL with support for the following backends:")
|
||||
MESSAGE(STATUS " ${BACKENDS}")
|
||||
MESSAGE(STATUS "")
|
||||
|
||||
IF(WIN32 AND NOT HAVE_DSOUND)
|
||||
MESSAGE(STATUS "WARNING: Building the Windows version without DirectSound output")
|
||||
MESSAGE(STATUS " This is probably NOT what you want!")
|
||||
MESSAGE(STATUS "")
|
||||
ENDIF()
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#ifndef _AL_AUXEFFECTSLOT_H_
|
||||
#define _AL_AUXEFFECTSLOT_H_
|
||||
|
||||
#include "alEffect.h"
|
||||
#include "AL/al.h"
|
||||
#include "alEffect.h"
|
||||
#include "alFilter.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -28,7 +29,8 @@ typedef struct ALeffectslot
|
||||
ALuint ReverbReflectPos;
|
||||
ALuint ReverbLatePos;
|
||||
ALfloat ReverbDecayGain;
|
||||
ALfloat LastDecaySample;
|
||||
|
||||
FILTER iirFilter;
|
||||
|
||||
ALuint refcount;
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ typedef struct ALbuffer_struct
|
||||
ALshort *data;
|
||||
ALsizei size;
|
||||
ALsizei frequency;
|
||||
ALsizei padding;
|
||||
ALenum state;
|
||||
ALuint refcount; // Number of sources using this buffer (deletion can only occur when this is 0)
|
||||
struct ALbuffer_struct *next;
|
||||
|
||||
@@ -7,6 +7,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FILTER_SECTIONS 2 /* 2 filter sections for 24 db/oct filter */
|
||||
|
||||
typedef struct {
|
||||
float history[2*FILTER_SECTIONS]; /* history in filter */
|
||||
float coef[4*FILTER_SECTIONS + 1]; /* coefficients of filter */
|
||||
} FILTER;
|
||||
|
||||
#define AL_FILTER_TYPE 0x8001
|
||||
|
||||
#define AL_FILTER_NULL 0x0000
|
||||
@@ -48,6 +55,8 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pf
|
||||
|
||||
ALvoid ReleaseALFilters(ALvoid);
|
||||
|
||||
int InitLowPassFilter(ALCcontext *Context, FILTER *iir);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -103,8 +103,6 @@ static inline void Sleep(ALuint t)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern CRITICAL_SECTION _alMutex;
|
||||
|
||||
extern char _alDebug[256];
|
||||
|
||||
#define AL_PRINT(...) do { \
|
||||
@@ -125,6 +123,9 @@ extern char _alDebug[256];
|
||||
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
|
||||
#define AIRABSORBGAINHF (0.994f)
|
||||
|
||||
#define LOWPASSFREQCUTOFF (5000)
|
||||
|
||||
|
||||
typedef struct {
|
||||
ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
|
||||
void (*ClosePlayback)(ALCdevice*);
|
||||
@@ -200,7 +201,7 @@ struct ALCcontext_struct
|
||||
ALint lNumStereoSources;
|
||||
|
||||
ALCdevice *Device;
|
||||
ALCchar ExtensionList[1024];
|
||||
const ALCchar *ExtensionList;
|
||||
|
||||
struct bs2b *bs2b;
|
||||
|
||||
|
||||
@@ -70,18 +70,19 @@ typedef struct ALsource
|
||||
ALfilter WetFilter;
|
||||
} Send[MAX_SENDS];
|
||||
|
||||
ALfloat LastDrySample;
|
||||
ALfloat LastWetSample;
|
||||
|
||||
ALboolean DryGainHFAuto;
|
||||
ALboolean WetGainAuto;
|
||||
ALboolean WetGainHFAuto;
|
||||
ALfloat OuterGainHF;
|
||||
|
||||
FILTER iirFilter;
|
||||
|
||||
ALfloat AirAbsorptionFactor;
|
||||
|
||||
ALfloat RoomRolloffFactor;
|
||||
|
||||
ALfloat DopplerFactor;
|
||||
|
||||
// Index to itself
|
||||
ALuint source;
|
||||
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alBuffer.h"
|
||||
#include "alFilter.h"
|
||||
#include "alEffect.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alThunk.h"
|
||||
|
||||
CRITICAL_SECTION _alMutex;
|
||||
|
||||
#ifdef _WIN32
|
||||
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
|
||||
{
|
||||
(void)lpReserved;
|
||||
|
||||
// Perform actions based on the reason for calling.
|
||||
switch(ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
DisableThreadLibraryCalls(hModule);
|
||||
break;
|
||||
|
||||
case DLL_PROCESS_DETACH:
|
||||
ReleaseALC();
|
||||
ReleaseALBuffers();
|
||||
ReleaseALEffects();
|
||||
ReleaseALFilters();
|
||||
FreeALConfig();
|
||||
ALTHUNK_EXIT();
|
||||
DeleteCriticalSection(&_alMutex);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
#ifdef HAVE_GCC_DESTRUCTOR
|
||||
static void my_deinit() __attribute__((destructor));
|
||||
static void my_deinit()
|
||||
{
|
||||
static ALenum once = AL_FALSE;
|
||||
if(once) return;
|
||||
once = AL_TRUE;
|
||||
|
||||
ReleaseALC();
|
||||
ReleaseALBuffers();
|
||||
ReleaseALEffects();
|
||||
ReleaseALFilters();
|
||||
FreeALConfig();
|
||||
ALTHUNK_EXIT();
|
||||
DeleteCriticalSection(&_alMutex);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -71,6 +71,8 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
|
||||
break;
|
||||
}
|
||||
|
||||
InitLowPassFilter(Context, &(*list)->iirFilter);
|
||||
|
||||
(*list)->Gain = 1.0;
|
||||
(*list)->AuxSendAuto = AL_TRUE;
|
||||
(*list)->refcount = 0;
|
||||
@@ -522,7 +524,7 @@ ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if(Context->AuxiliaryEffectSlotCount > 0)
|
||||
AL_PRINT("alcDestroyContext(): %d AuxiliaryEffectSlot(s) NOT deleted\n", Context->AuxiliaryEffectSlotCount);
|
||||
AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context->AuxiliaryEffectSlotCount);
|
||||
#endif
|
||||
|
||||
while(Context->AuxiliaryEffectSlot)
|
||||
|
||||
+97
-72
@@ -142,63 +142,59 @@ ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint *puiBuffers)
|
||||
// Check we are actually Deleting some Buffers
|
||||
if (n >= 0)
|
||||
{
|
||||
if ((ALuint)n <= g_uiBufferCount)
|
||||
// Check that all the buffers are valid and can actually be deleted
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
// Check that all the buffers are valid and can actually be deleted
|
||||
for (i = 0; i < n; i++)
|
||||
// Check for valid Buffer ID (can be NULL buffer)
|
||||
if (alIsBuffer(puiBuffers[i]))
|
||||
{
|
||||
// Check for valid Buffer ID (can be NULL buffer)
|
||||
if (alIsBuffer(puiBuffers[i]))
|
||||
// If not the NULL buffer, check that the reference count is 0
|
||||
ALBuf = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
|
||||
if (ALBuf)
|
||||
{
|
||||
// If not the NULL buffer, check that the reference count is 0
|
||||
ALBuf = ((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
|
||||
if (ALBuf)
|
||||
if (ALBuf->refcount != 0)
|
||||
{
|
||||
if (ALBuf->refcount != 0)
|
||||
{
|
||||
// Buffer still in use, cannot be deleted
|
||||
alSetError(AL_INVALID_OPERATION);
|
||||
bFailed = AL_TRUE;
|
||||
}
|
||||
// Buffer still in use, cannot be deleted
|
||||
alSetError(AL_INVALID_OPERATION);
|
||||
bFailed = AL_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid Buffer
|
||||
alSetError(AL_INVALID_NAME);
|
||||
bFailed = AL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// If all the Buffers were valid (and have Reference Counts of 0), then we can delete them
|
||||
if (!bFailed)
|
||||
else
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
// Invalid Buffer
|
||||
alSetError(AL_INVALID_NAME);
|
||||
bFailed = AL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// If all the Buffers were valid (and have Reference Counts of 0), then we can delete them
|
||||
if (!bFailed)
|
||||
{
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (puiBuffers[i] && alIsBuffer(puiBuffers[i]))
|
||||
{
|
||||
ALbuffer **list = &g_pBuffers;
|
||||
|
||||
ALBuf=((ALbuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
|
||||
if (ALBuf)
|
||||
{
|
||||
ALbuffer **list = &g_pBuffers;
|
||||
while(*list && *list != ALBuf)
|
||||
list = &(*list)->next;
|
||||
while(*list && *list != ALBuf)
|
||||
list = &(*list)->next;
|
||||
|
||||
if(*list)
|
||||
*list = (*list)->next;
|
||||
if(*list)
|
||||
*list = (*list)->next;
|
||||
|
||||
// Release the memory used to store audio data
|
||||
free(ALBuf->data);
|
||||
// Release the memory used to store audio data
|
||||
free(ALBuf->data);
|
||||
|
||||
// Release buffer structure
|
||||
ALTHUNK_REMOVEENTRY(puiBuffers[i]);
|
||||
memset(ALBuf, 0, sizeof(ALbuffer));
|
||||
g_uiBufferCount--;
|
||||
free(ALBuf);
|
||||
}
|
||||
// Release buffer structure
|
||||
ALTHUNK_REMOVEENTRY(puiBuffers[i]);
|
||||
memset(ALBuf, 0, sizeof(ALbuffer));
|
||||
g_uiBufferCount--;
|
||||
free(ALBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_NAME);
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
@@ -266,7 +262,9 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
ALint RightSample,RightIndex;
|
||||
ALuint LeftIMACode,RightIMACode;
|
||||
ALbuffer *ALBuf;
|
||||
ALsizei padding;
|
||||
ALsizei i,j,k;
|
||||
ALvoid *temp;
|
||||
|
||||
Context = alcGetCurrentContext();
|
||||
SuspendContext(Context);
|
||||
@@ -308,6 +306,9 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
break;
|
||||
}
|
||||
|
||||
padding = freq / LOWPASSFREQCUTOFF;
|
||||
if(padding < 1) padding = 1;
|
||||
|
||||
switch(OrigBytes)
|
||||
{
|
||||
case 1:
|
||||
@@ -315,10 +316,10 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
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)
|
||||
temp = realloc(ALBuf->data, (padding*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (temp)
|
||||
{
|
||||
ALBuf->data = temp;
|
||||
for (i = 0;i < size;i+=4)
|
||||
{
|
||||
ALBuf->data[i+0] = 0;
|
||||
@@ -326,12 +327,13 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
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);
|
||||
memset(&(ALBuf->data[size]), 0, padding*NewChannels*2);
|
||||
|
||||
ALBuf->format = NewFormat;
|
||||
ALBuf->eOriginalFormat = format;
|
||||
ALBuf->size = size*1*sizeof(ALshort);
|
||||
ALBuf->frequency = freq;
|
||||
ALBuf->padding = padding;
|
||||
}
|
||||
else
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
@@ -341,10 +343,10 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
size /= sizeof(ALshort);
|
||||
size *= 2;
|
||||
|
||||
// Allocate 8 extra samples
|
||||
ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (ALBuf->data)
|
||||
temp = realloc(ALBuf->data, (padding*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (temp)
|
||||
{
|
||||
ALBuf->data = temp;
|
||||
for (i = 0;i < size;i+=4)
|
||||
{
|
||||
ALBuf->data[i+0] = 0;
|
||||
@@ -352,12 +354,13 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
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);
|
||||
memset(&(ALBuf->data[size]), 0, padding*NewChannels*2);
|
||||
|
||||
ALBuf->format = NewFormat;
|
||||
ALBuf->eOriginalFormat = format;
|
||||
ALBuf->size = size*1*sizeof(ALshort);
|
||||
ALBuf->frequency = freq;
|
||||
ALBuf->padding = padding;
|
||||
}
|
||||
else
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
@@ -367,11 +370,11 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
size /= sizeof(ALfloat);
|
||||
size *= 2;
|
||||
|
||||
// Allocate 8 extra samples
|
||||
ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (ALBuf->data)
|
||||
temp = realloc(ALBuf->data, (padding*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (temp)
|
||||
{
|
||||
ALint smp;
|
||||
ALBuf->data = temp;
|
||||
for (i = 0;i < size;i+=4)
|
||||
{
|
||||
ALBuf->data[i+0] = 0;
|
||||
@@ -385,12 +388,13 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
smp = max(smp, -32768);
|
||||
ALBuf->data[i+3] = (ALshort)smp;
|
||||
}
|
||||
memset(&(ALBuf->data[size]), 0, 16*NewChannels);
|
||||
memset(&(ALBuf->data[size]), 0, padding*NewChannels*2);
|
||||
|
||||
ALBuf->format = NewFormat;
|
||||
ALBuf->eOriginalFormat = format;
|
||||
ALBuf->size = size*1*sizeof(ALshort);
|
||||
ALBuf->frequency = freq;
|
||||
ALBuf->padding = padding;
|
||||
}
|
||||
else
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
@@ -428,15 +432,19 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
break;
|
||||
|
||||
case AL_FORMAT_MONO_IMA4:
|
||||
padding = freq / LOWPASSFREQCUTOFF;
|
||||
if(padding < 1) padding = 1;
|
||||
|
||||
// Here is where things vary:
|
||||
// nVidia and Apple use 64+1 samples per block => block_size=36 bytes
|
||||
// Most PC sound software uses 2040+1 samples per block -> block_size=1024 bytes
|
||||
if ((size%36) == 0)
|
||||
{
|
||||
// Allocate 8 extra samples (16 bytes)
|
||||
ALBuf->data=realloc(ALBuf->data,16+(size/36)*(65*sizeof(ALshort)));
|
||||
if (ALBuf->data)
|
||||
// Allocate extra padding samples
|
||||
temp=realloc(ALBuf->data,padding*2+(size/36)*(65*sizeof(ALshort)));
|
||||
if (temp)
|
||||
{
|
||||
ALBuf->data = temp;
|
||||
ALBuf->format = AL_FORMAT_MONO16;
|
||||
ALBuf->eOriginalFormat = AL_FORMAT_MONO_IMA4;
|
||||
IMAData=(ALuint *)data;
|
||||
@@ -478,9 +486,10 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
IMAData++;
|
||||
}
|
||||
}
|
||||
memset(&(ALBuf->data[(size/36*65)]), 0, 16);
|
||||
memset(&(ALBuf->data[(size/36*65)]), 0, padding*2);
|
||||
ALBuf->size=size/36*65*sizeof(ALshort);
|
||||
ALBuf->frequency=freq;
|
||||
ALBuf->padding=padding;
|
||||
}
|
||||
else
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
@@ -490,15 +499,19 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
break;
|
||||
|
||||
case AL_FORMAT_STEREO_IMA4:
|
||||
padding = freq / LOWPASSFREQCUTOFF;
|
||||
if(padding < 1) padding = 1;
|
||||
|
||||
// Here is where things vary:
|
||||
// nVidia and Apple use 64+1 samples per channel per block => block_size=72 bytes
|
||||
// Most PC sound software uses 2040+1 samples per channel per block -> block_size=2048 bytes
|
||||
if ((size%72) == 0)
|
||||
{
|
||||
// Allocate 8 extra samples (32 bytes)
|
||||
ALBuf->data=realloc(ALBuf->data,32+(size/72)*(2*65*sizeof(ALshort)));
|
||||
if (ALBuf->data)
|
||||
// Allocate extra padding samples
|
||||
temp=realloc(ALBuf->data,padding*2*2+(size/72)*(2*65*sizeof(ALshort)));
|
||||
if (temp)
|
||||
{
|
||||
ALBuf->data = temp;
|
||||
ALBuf->format = AL_FORMAT_STEREO16;
|
||||
ALBuf->eOriginalFormat = AL_FORMAT_STEREO_IMA4;
|
||||
IMAData=(ALuint *)data;
|
||||
@@ -569,9 +582,10 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
|
||||
IMAData+=2;
|
||||
}
|
||||
}
|
||||
memset(&(ALBuf->data[(size/72*2*65)]), 0, 32);
|
||||
memset(&(ALBuf->data[(size/72*2*65)]), 0, padding*2*2);
|
||||
ALBuf->size=size/72*2*65*sizeof(ALshort);
|
||||
ALBuf->frequency=freq;
|
||||
ALBuf->padding=padding;
|
||||
}
|
||||
else
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
@@ -997,6 +1011,8 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
|
||||
ALuint NewChannels = aluChannelsFromFormat(NewFormat);
|
||||
ALuint OrigBytes = aluBytesFromFormat(OrigFormat);
|
||||
ALuint OrigChannels = aluChannelsFromFormat(OrigFormat);
|
||||
ALsizei padding = freq / LOWPASSFREQCUTOFF;
|
||||
ALvoid *temp;
|
||||
ALsizei i;
|
||||
|
||||
assert(aluBytesFromFormat(NewFormat) == 2);
|
||||
@@ -1008,24 +1024,29 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure at least one padding byte for the bilinear filter */
|
||||
if(padding < 1)
|
||||
padding = 1;
|
||||
|
||||
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)
|
||||
temp = realloc(ALBuf->data, (padding*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (temp)
|
||||
{
|
||||
ALBuf->data = temp;
|
||||
for (i = 0;i < size;i++)
|
||||
ALBuf->data[i] = (ALshort)((data[i]-128) << 8);
|
||||
memset(&(ALBuf->data[size]), 0, 16*NewChannels);
|
||||
memset(&(ALBuf->data[size]), 0, padding*NewChannels*2);
|
||||
|
||||
ALBuf->format = NewFormat;
|
||||
ALBuf->eOriginalFormat = OrigFormat;
|
||||
ALBuf->size = size*1*sizeof(ALshort);
|
||||
ALBuf->frequency = freq;
|
||||
ALBuf->padding = padding;
|
||||
}
|
||||
else
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
@@ -1035,16 +1056,18 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
|
||||
size /= sizeof(ALshort);
|
||||
|
||||
// Allocate 8 extra samples
|
||||
ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (ALBuf->data)
|
||||
temp = realloc(ALBuf->data, (padding*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (temp)
|
||||
{
|
||||
ALBuf->data = temp;
|
||||
memcpy(ALBuf->data, data, size*1*sizeof(ALshort));
|
||||
memset(&(ALBuf->data[size]), 0, 16*NewChannels);
|
||||
memset(&(ALBuf->data[size]), 0, padding*NewChannels*2);
|
||||
|
||||
ALBuf->format = NewFormat;
|
||||
ALBuf->eOriginalFormat = OrigFormat;
|
||||
ALBuf->size = size*1*sizeof(ALshort);
|
||||
ALBuf->frequency = freq;
|
||||
ALBuf->padding = padding;
|
||||
}
|
||||
else
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
@@ -1054,10 +1077,11 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
|
||||
size /= sizeof(ALfloat);
|
||||
|
||||
// Allocate 8 extra samples
|
||||
ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (ALBuf->data)
|
||||
temp = realloc(ALBuf->data, (padding*NewChannels + size) * (1*sizeof(ALshort)));
|
||||
if (temp)
|
||||
{
|
||||
ALint smp;
|
||||
ALBuf->data = temp;
|
||||
for (i = 0;i < size;i++)
|
||||
{
|
||||
smp = (((ALfloat*)data)[i] * 32767.5f - 0.5f);
|
||||
@@ -1065,12 +1089,13 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
|
||||
smp = max(smp, -32768);
|
||||
ALBuf->data[i] = (ALshort)smp;
|
||||
}
|
||||
memset(&(ALBuf->data[size]), 0, 16*NewChannels);
|
||||
memset(&(ALBuf->data[size]), 0, padding*NewChannels*2);
|
||||
|
||||
ALBuf->format = NewFormat;
|
||||
ALBuf->eOriginalFormat = OrigFormat;
|
||||
ALBuf->size = size*1*sizeof(ALshort);
|
||||
ALBuf->frequency = freq;
|
||||
ALBuf->padding = padding;
|
||||
}
|
||||
else
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
@@ -1094,7 +1119,7 @@ ALvoid ReleaseALBuffers(ALvoid)
|
||||
|
||||
#ifdef _DEBUG
|
||||
if(g_uiBufferCount > 0)
|
||||
AL_PRINT("exit() %d Buffer(s) NOT deleted\n", g_uiBufferCount);
|
||||
AL_PRINT("exit(): deleting %d Buffer(s)\n", g_uiBufferCount);
|
||||
#endif
|
||||
|
||||
ALBuffer = g_pBuffers;
|
||||
|
||||
+1
-1
@@ -590,7 +590,7 @@ ALvoid ReleaseALEffects(ALvoid)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if(g_EffectCount > 0)
|
||||
AL_PRINT("exit() %d Effect(s) NOT deleted\n", g_EffectCount);
|
||||
AL_PRINT("exit(): deleting %d Effect(s)\n", g_EffectCount);
|
||||
#endif
|
||||
|
||||
while(g_EffectList)
|
||||
|
||||
+40
-38
@@ -221,26 +221,29 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue
|
||||
{
|
||||
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
|
||||
|
||||
switch(param)
|
||||
switch(ALFilter->type)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
if(ALFilter->type == AL_FILTER_LOWPASS)
|
||||
case AL_FILTER_LOWPASS:
|
||||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
if(flValue >= 0.0f && flValue <= 1.0f)
|
||||
ALFilter->Gain = flValue;
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_LOWPASS_GAINHF:
|
||||
if(ALFilter->type == AL_FILTER_LOWPASS)
|
||||
{
|
||||
case AL_LOWPASS_GAINHF:
|
||||
if(flValue >= 0.0f && flValue <= 1.0f)
|
||||
ALFilter->GainHF = flValue;
|
||||
}
|
||||
else
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -265,13 +268,8 @@ AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflVa
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
case AL_LOWPASS_GAINHF:
|
||||
alFilterf(filter, param, pflValues[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
alFilterf(filter, param, pflValues[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -285,15 +283,19 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piVal
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
(void)piValue;
|
||||
|
||||
Context = alcGetCurrentContext();
|
||||
SuspendContext(Context);
|
||||
|
||||
if (filter && alIsFilter(filter))
|
||||
{
|
||||
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case AL_FILTER_TYPE:
|
||||
*piValue = ALFilter->type;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -309,8 +311,6 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piVa
|
||||
{
|
||||
ALCcontext *Context;
|
||||
|
||||
(void)piValues;
|
||||
|
||||
Context = alcGetCurrentContext();
|
||||
SuspendContext(Context);
|
||||
|
||||
@@ -318,6 +318,10 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piVa
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_FILTER_TYPE:
|
||||
alGetFilteri(filter, param, piValues);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -340,20 +344,23 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pfl
|
||||
{
|
||||
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
|
||||
|
||||
switch(param)
|
||||
switch(ALFilter->type)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
if(ALFilter->type == AL_FILTER_LOWPASS)
|
||||
case AL_FILTER_LOWPASS:
|
||||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
*pflValue = ALFilter->Gain;
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
break;
|
||||
|
||||
case AL_LOWPASS_GAINHF:
|
||||
if(ALFilter->type == AL_FILTER_LOWPASS)
|
||||
case AL_LOWPASS_GAINHF:
|
||||
*pflValue = ALFilter->GainHF;
|
||||
else
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -378,13 +385,8 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pf
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_LOWPASS_GAIN:
|
||||
case AL_LOWPASS_GAINHF:
|
||||
alGetFilterf(filter, param, pflValues);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
alGetFilterf(filter, param, pflValues);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -399,7 +401,7 @@ ALvoid ReleaseALFilters(ALvoid)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if(g_FilterCount > 0)
|
||||
AL_PRINT("exit() %d Filter(s) NOT deleted\n", g_FilterCount);
|
||||
AL_PRINT("exit(): deleting %d Filter(s)\n", g_FilterCount);
|
||||
#endif
|
||||
|
||||
while(g_FilterList)
|
||||
|
||||
+67
-63
@@ -75,6 +75,8 @@ ALAPI ALvoid ALAPIENTRY alGenSources(ALsizei n,ALuint *sources)
|
||||
break;
|
||||
}
|
||||
|
||||
InitLowPassFilter(Context, &(*list)->iirFilter);
|
||||
|
||||
sources[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
|
||||
(*list)->source = sources[i];
|
||||
|
||||
@@ -137,73 +139,64 @@ ALAPI ALvoid ALAPIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
|
||||
|
||||
if (Device)
|
||||
{
|
||||
if ((ALuint)n <= Context->SourceCount)
|
||||
// Check that all Sources are valid (and can therefore be deleted)
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
// Check that all Sources are valid (and can therefore be deleted)
|
||||
for (i = 0; i < n; i++)
|
||||
if (!alIsSource(sources[i]))
|
||||
{
|
||||
if (!alIsSource(sources[i]))
|
||||
{
|
||||
alSetError(AL_INVALID_NAME);
|
||||
bSourcesValid = AL_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bSourcesValid)
|
||||
{
|
||||
// All Sources are valid, and can be deleted
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
// Recheck that the Source is valid, because there could be duplicated Source names
|
||||
if (alIsSource(sources[i]))
|
||||
{
|
||||
ALSource=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
|
||||
alSourceStop((ALuint)ALSource->source);
|
||||
|
||||
// For each buffer in the source's queue, decrement its reference counter and remove it
|
||||
while (ALSource->queue != NULL)
|
||||
{
|
||||
ALBufferList = ALSource->queue;
|
||||
// Decrement buffer's reference counter
|
||||
if (ALBufferList->buffer != 0)
|
||||
((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->refcount--;
|
||||
// Update queue to point to next element in list
|
||||
ALSource->queue = ALBufferList->next;
|
||||
// Release memory allocated for buffer list item
|
||||
free(ALBufferList);
|
||||
}
|
||||
|
||||
for(j = 0;j < MAX_SENDS;++j)
|
||||
{
|
||||
if(ALSource->Send[j].Slot)
|
||||
ALSource->Send[j].Slot->refcount--;
|
||||
ALSource->Send[j].Slot = NULL;
|
||||
}
|
||||
|
||||
// Decrement Source count
|
||||
Context->SourceCount--;
|
||||
|
||||
// Remove Source from list of Sources
|
||||
list = &Context->Source;
|
||||
while(*list && *list != ALSource)
|
||||
list = &(*list)->next;
|
||||
|
||||
if(*list)
|
||||
*list = (*list)->next;
|
||||
ALTHUNK_REMOVEENTRY(ALSource->source);
|
||||
|
||||
memset(ALSource,0,sizeof(ALsource));
|
||||
free(ALSource);
|
||||
}
|
||||
}
|
||||
|
||||
alSetError(AL_INVALID_NAME);
|
||||
bSourcesValid = AL_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (bSourcesValid)
|
||||
{
|
||||
// Trying to delete more Sources than have been generated
|
||||
alSetError(AL_INVALID_NAME);
|
||||
// All Sources are valid, and can be deleted
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
// Recheck that the Source is valid, because there could be duplicated Source names
|
||||
if (alIsSource(sources[i]))
|
||||
{
|
||||
ALSource=((ALsource *)ALTHUNK_LOOKUPENTRY(sources[i]));
|
||||
alSourceStop((ALuint)ALSource->source);
|
||||
|
||||
// For each buffer in the source's queue, decrement its reference counter and remove it
|
||||
while (ALSource->queue != NULL)
|
||||
{
|
||||
ALBufferList = ALSource->queue;
|
||||
// Decrement buffer's reference counter
|
||||
if (ALBufferList->buffer != 0)
|
||||
((ALbuffer*)(ALTHUNK_LOOKUPENTRY(ALBufferList->buffer)))->refcount--;
|
||||
// Update queue to point to next element in list
|
||||
ALSource->queue = ALBufferList->next;
|
||||
// Release memory allocated for buffer list item
|
||||
free(ALBufferList);
|
||||
}
|
||||
|
||||
for(j = 0;j < MAX_SENDS;++j)
|
||||
{
|
||||
if(ALSource->Send[j].Slot)
|
||||
ALSource->Send[j].Slot->refcount--;
|
||||
ALSource->Send[j].Slot = NULL;
|
||||
}
|
||||
|
||||
// Decrement Source count
|
||||
Context->SourceCount--;
|
||||
|
||||
// Remove Source from list of Sources
|
||||
list = &Context->Source;
|
||||
while(*list && *list != ALSource)
|
||||
list = &(*list)->next;
|
||||
|
||||
if(*list)
|
||||
*list = (*list)->next;
|
||||
ALTHUNK_REMOVEENTRY(ALSource->source);
|
||||
|
||||
memset(ALSource,0,sizeof(ALsource));
|
||||
free(ALSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -934,6 +927,10 @@ ALAPI ALvoid ALAPIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflV
|
||||
*pflValue = pSource->RoomRolloffFactor;
|
||||
break;
|
||||
|
||||
case AL_DOPPLER_FACTOR:
|
||||
*pflValue = pSource->DopplerFactor;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -1034,6 +1031,7 @@ ALAPI ALvoid ALAPIENTRY alGetSourcefv(ALuint source, ALenum eParam, ALfloat *pfl
|
||||
case AL_MAX_GAIN:
|
||||
case AL_MAX_DISTANCE:
|
||||
case AL_ROLLOFF_FACTOR:
|
||||
case AL_DOPPLER_FACTOR:
|
||||
case AL_CONE_OUTER_GAIN:
|
||||
case AL_SEC_OFFSET:
|
||||
case AL_SAMPLE_OFFSET:
|
||||
@@ -1184,6 +1182,10 @@ ALAPI ALvoid ALAPIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValu
|
||||
*plValue = pSource->WetGainHFAuto;
|
||||
break;
|
||||
|
||||
case AL_DOPPLER_FACTOR:
|
||||
*plValue = (ALint)pSource->DopplerFactor;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -1291,6 +1293,7 @@ ALAPI void ALAPIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValue
|
||||
case AL_BYTE_OFFSET:
|
||||
case AL_MAX_DISTANCE:
|
||||
case AL_ROLLOFF_FACTOR:
|
||||
case AL_DOPPLER_FACTOR:
|
||||
case AL_REFERENCE_DISTANCE:
|
||||
case AL_SOURCE_TYPE:
|
||||
case AL_DIRECT_FILTER:
|
||||
@@ -1980,6 +1983,7 @@ static ALvoid InitSourceParams(ALsource *pSource)
|
||||
pSource->WetGainHFAuto = AL_TRUE;
|
||||
pSource->AirAbsorptionFactor = 0.0f;
|
||||
pSource->RoomRolloffFactor = 0.0f;
|
||||
pSource->DopplerFactor = 1.0f;
|
||||
|
||||
pSource->state = AL_INITIAL;
|
||||
pSource->lSourceType = AL_UNDETERMINED;
|
||||
@@ -2288,7 +2292,7 @@ ALvoid ReleaseALSources(ALCcontext *Context)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if(Context->SourceCount > 0)
|
||||
AL_PRINT("alcDestroyContext(): %d Source(s) NOT deleted\n", Context->SourceCount);
|
||||
AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", Context->SourceCount);
|
||||
#endif
|
||||
|
||||
while(Context->Source)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: OpenAL
|
||||
Description: OpenAL is a cross-platform 3D audio API
|
||||
Requires: @PKG_CONFIG_REQUIRES@
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -l@LIBNAME@ @PKG_CONFIG_LIBS@
|
||||
Cflags: -I${includedir}
|
||||
+1
-1
@@ -38,7 +38,7 @@ cf_level = 0 # Sets the crossfeed level for stereo output. Valid values are:
|
||||
|
||||
frequency = 44100 # Sets the output frequency. Default is 44100
|
||||
|
||||
refresh = 8192 # Sets the buffer size, in frames. Default is 8192. Note that
|
||||
refresh = 4096 # Sets the buffer size, in frames. Default is 4096. Note that
|
||||
# the actual granularity may or may not be less than this.
|
||||
|
||||
sources = 256 # Sets the maximum number of allocatable sources. Lower values
|
||||
|
||||
@@ -166,11 +166,6 @@ typedef void ALCvoid;
|
||||
#define ALC_ATTRIBUTES_SIZE 0x1002
|
||||
#define ALC_ALL_ATTRIBUTES 0x1003
|
||||
|
||||
/**
|
||||
* ALC_ENUMERATE_ALL_EXT enums
|
||||
*/
|
||||
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
|
||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
|
||||
/**
|
||||
* Capture extension
|
||||
|
||||
+33
-4
@@ -25,10 +25,20 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_float32
|
||||
#define AL_EXT_float32 1
|
||||
#define AL_FORMAT_MONO_FLOAT32 0x10010
|
||||
#define AL_FORMAT_STEREO_FLOAT32 0x10011
|
||||
#ifndef AL_LOKI_IMA_ADPCM_format
|
||||
#define AL_LOKI_IMA_ADPCM_format 1
|
||||
#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000
|
||||
#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001
|
||||
#endif
|
||||
|
||||
#ifndef AL_LOKI_WAVE_format
|
||||
#define AL_LOKI_WAVE_format 1
|
||||
#define AL_FORMAT_WAVE_EXT 0x10002
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_vorbis
|
||||
#define AL_EXT_vorbis 1
|
||||
#define AL_FORMAT_VORBIS_EXT 0x10003
|
||||
#endif
|
||||
|
||||
#ifndef AL_LOKI_quadriphonic
|
||||
@@ -37,6 +47,25 @@ extern "C" {
|
||||
#define AL_FORMAT_QUAD16_LOKI 0x10005
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_float32
|
||||
#define AL_EXT_float32 1
|
||||
#define AL_FORMAT_MONO_FLOAT32 0x10010
|
||||
#define AL_FORMAT_STEREO_FLOAT32 0x10011
|
||||
#endif
|
||||
|
||||
#ifndef ALC_LOKI_audio_channel
|
||||
#define ALC_LOKI_audio_channel 1
|
||||
#define ALC_CHAN_MAIN_LOKI 0x500001
|
||||
#define ALC_CHAN_PCM_LOKI 0x500002
|
||||
#define ALC_CHAN_CD_LOKI 0x500003
|
||||
#endif
|
||||
|
||||
#ifndef ALC_ENUMERATE_ALL_EXT
|
||||
#define ALC_ENUMERATE_ALL_EXT 1
|
||||
#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
|
||||
#define ALC_ALL_DEVICES_SPECIFIER 0x1013
|
||||
#endif
|
||||
|
||||
#ifndef AL_EXT_MCFORMATS
|
||||
#define AL_EXT_MCFORMATS 1
|
||||
#define AL_FORMAT_QUAD8 0x1204
|
||||
|
||||
Reference in New Issue
Block a user