Compare commits

...

51 Commits

Author SHA1 Message Date
Chris Robinson f1414c650e Release 1.5.304 2008-07-27 19:58:32 -07:00
Chris Robinson 869b041f2f Reduce the default buffer size to 4096
Should help with latency issues some people have and not put too much extra
burden on the mixer, hopefully
2008-07-26 21:07:08 -07:00
Chris Robinson 8621fbb015 Improve getting and setting EFX filter parameters 2008-07-26 18:32:45 -07:00
Chris Robinson 597e01153e Use arrays instead of pointer-to-arrays for the low-pass filter 2008-07-26 17:13:50 -07:00
Chris Robinson d3e5fcd13e Fix some calculations for the reverb buffer 2008-07-26 01:57:04 -07:00
Chris Robinson 3e0f9cc716 Make the filter processing function inline 2008-07-26 00:58:54 -07:00
Chris Robinson c7e49c9f57 Implement yet another low-pass filter
This one using the Butterworth IIR filter design
2008-07-25 19:31:12 -07:00
Chris Robinson e2ed8ff2bf Use a temp pointer when realloc()ing
So the original data isn't lost on out-of-memory conditions
2008-07-24 13:44:26 -07:00
Chris Robinson 559c786d0c Specify padding per buffer, and make sure it's large enough for the filter step 2008-07-24 00:41:25 -07:00
Chris Robinson c3a7480961 Don't advertise extra samples for mixing 2008-07-23 23:27:38 -07:00
Chris Robinson a75e75aef5 Implement an alternative low-pass filter
This method samples from the buffer so that it gets a time-correct 5khz stream,
which is subtracted from the original sample and has the high-frequency gain
applied, then added back.
A better method may be to average all the samples from the current one to the
one freq/5000 away, instead of bilinear filtering the two nearest freq/5000
apart. Processing cost will need to determine its viability
2008-07-23 22:29:53 -07:00
Chris Robinson d45b1207d0 Make sure the correct libname is used for pkg-config 2008-07-23 11:58:36 -07:00
Chris Robinson 5a9e24dea1 Add a warning when building on Windows with the DSound backend disabled 2008-07-23 00:51:55 -07:00
Chris Robinson dc8132e965 Add a pkg-config file to install on the system 2008-07-22 18:42:53 -07:00
Chris Robinson 20bcdc1ef6 Add AL_LOKI_IMA_ADPCM_format and AL_EXT_vorbis tokens to alext.h 2008-07-22 14:45:31 -07:00
Chris Robinson 93c0f61050 Clarify implicit destruction warnings 2008-07-22 14:29:27 -07:00
Chris Robinson 3a8c543f8b Move ALC_ENUMERATE_ALL_EXT tokens to alext.h 2008-07-22 13:50:08 -07:00
Chris Robinson 9e96156451 Add AL_LOKI_WAVE_format tokens to alext.h 2008-07-22 13:45:26 -07:00
Chris Robinson 19aabd6d02 Add ALC_LOKI_audio_channel tokens to alext.h 2008-07-22 13:16:58 -07:00
Chris Robinson 87b5d7bc7b Store extension list with a pointer, not a per-context array 2008-07-22 12:39:10 -07:00
Chris Robinson 646714b585 Set the new linking policy for CMake 2.6 to avoid warnings 2008-07-22 11:26:56 -07:00
Chris Robinson eba60c30c5 Don't force initialization when shutting down
Thanks to Michael Simms
2008-07-17 18:45:21 -07:00
Chris Robinson e66bb09156 Move (de)initialization into ALc.c and remove unneeded file 2008-07-17 18:38:07 -07:00
Chris Robinson 0042b1f80d Implement doppler factor source property 2008-07-15 02:33:05 -07:00
Chris Robinson 6d416ee734 Add the reverb room rolloff to the source room rolloff, not override 2008-07-15 02:23:53 -07:00
Chris Robinson 97d3a45aff Don't check the number of objects being deleted with the number currently allocated
Since apps can validly delete buffer 0, and delete the same source/buffer multiple times in a single call
2008-07-11 09:12:11 -07:00
Chris Robinson 9e9ff44b17 Use volatile for member variables that are changed in a different thread 2008-07-10 20:36:28 -07:00
Chris Robinson f369be148f Reduce the mix buffer sizes by half
Nearly 3MB is a bit much. Could reduce it further, but this is good enough for now.
2008-07-08 19:37:14 -07:00
Chris Robinson 3a09e446b3 Leave SourceToListener untransformed for use with untransformed velocities
Distance is also left untransformed so cone calculations with SoundToListener
are correct
2008-07-03 03:13:43 -07:00
Chris Robinson 2d0b12e49e Store thread return value in the struct to avoid void*-to-uint casting 2008-06-17 19:46:37 -07:00
Chris Robinson 55e2f294ac Allow for overriding the default lib destination with LIB_INSTALL_DIR
So 64-bit builds can be optionally redirected to lib64
2008-06-06 18:39:18 -07:00
Chris Robinson 2a4b467f08 Make the project explicitly C
So it doesn't search for an unneeded C++ compiler
2008-06-06 18:33:13 -07:00
Chris Robinson 2ae9da696a Release 1.4.272 2008-06-04 20:47:20 -07:00
Chris Robinson 376997c3ef Fix config value check 2008-06-04 20:44:51 -07:00
Chris Robinson e963782b8c Release 1.4.270 2008-06-04 19:46:31 -07:00
Chris Robinson 86c01aa62c Install openal-info if it is built 2008-06-04 19:40:52 -07:00
Chris Robinson 15783d25e7 Don't override the format config option in DSound 2008-06-04 18:33:02 -07:00
Chris Robinson 3243f69f21 Use %AppData%\alsoft.ini for the config file in Windows 2008-06-04 18:09:21 -07:00
Chris Robinson 10a87f510c Protect RingBufferSize calculation with the mutex 2008-06-04 17:01:44 -07:00
Chris Robinson ca6feeda29 Make sure the lib is initialized when shutting down
Pretty ugly, but the destructor sequence relies in the mutex being initialized
2008-05-18 20:17:31 -07:00
Chris Robinson cecf778de3 Add addiitonal copyright line 2008-05-18 18:44:17 -07:00
Chris Robinson fe79ab351a Add a simple example that prints out some OpenAL info 2008-05-18 18:40:53 -07:00
Chris Robinson dc0a3a6653 Remove -fno-strict-aliasing as the code should be safe, now 2008-05-18 17:46:45 -07:00
Chris Robinson fed346c285 Fix source calculations for AL_SOURCE_RELATIVE mode
Make sure the source position and direction are properly put into listener-
space before working with them, and don't calculate the listener velocity for
relative coordinates
2008-05-18 16:52:38 -07:00
Chris Robinson cad9b367a5 Use pthread_mutexattr_setkind_np as a fallback to set a recursive mutex type
Some systems (FreeBSD) don't like setting it through pthread_mutexattr_settype
2008-05-15 21:35:51 -07:00
Chris Robinson 6e86146a25 Prepare the ALSA PCM handle before starting capture
Thanks to Jason Daly for pointing it out
2008-05-06 16:05:36 -07:00
Chris Robinson 49d9695ad9 Check the right struct member for the filter type 2008-04-12 07:25:18 -07:00
Chris Robinson e15bc6b9ba Fill the correct capture device list 2008-04-05 20:33:19 -07:00
Chris Robinson 28093a6dcb constify the pointer that holds the filename 2008-03-22 19:05:00 -07:00
Chris Robinson 2af5498804 Define _WIN32_WINNT to 0x0500 when including windows.h
VC7 appears to require that value, or higher, set and fails otherwise
2008-03-01 01:39:42 -08:00
Chris Robinson 2b42d7fdb8 Don't start the DSound playback thread is startup failed 2008-03-01 00:57:37 -08:00
29 changed files with 1250 additions and 427 deletions
+65 -11
View File
@@ -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
@@ -1249,8 +1303,8 @@ ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
ALCvoid ReleaseALC(ALCvoid)
{
#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)
+129 -94
View File
@@ -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,12 +298,43 @@ 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
aluCrossproduct(ALContext->Listener.Forward, ALContext->Listener.Up, U); // Right-vector
aluNormalize(U); // Normalized Right-vector
memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector
aluNormalize(V); // Normalized Up-vector
memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector
aluNormalize(N); // Normalized At-vector
Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
// Translate source position into listener space
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);
}
else
{
SourceToListener[0] = -Position[0];
SourceToListener[1] = -Position[1];
SourceToListener[2] = -Position[2];
}
aluNormalize(SourceToListener);
aluNormalize(Direction);
//2. Calculate distance attenuation
Distance = aluSqrt(aluDotproduct(Position, Position));
@@ -286,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;
@@ -356,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(Direction);
aluNormalize(SourceToListener);
Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * 180.0f /
3.141592654f;
if(Angle >= InnerAngle && Angle <= OuterAngle)
@@ -390,10 +441,10 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
//4. Calculate Velocity
if(DopplerFactor != 0.0f)
{
ALfloat flVSS, flVLS;
ALfloat flVSS, flVLS = 0.0f;
flVLS = aluDotproduct(ALContext->Listener.Velocity,
SourceToListener);
if(ALSource->bHeadRelative==AL_FALSE)
flVLS = aluDotproduct(ALContext->Listener.Velocity, SourceToListener);
flVSS = aluDotproduct(ALSource->vVelocity, SourceToListener);
flMaxVelocity = (DopplerVelocity * flSpeedOfSound) / DopplerFactor;
@@ -415,20 +466,8 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
else
pitch[0] = ALSource->flPitch;
//5. Align coordinate system axes
aluCrossproduct(ALContext->Listener.Forward, ALContext->Listener.Up, U); // Right-vector
aluNormalize(U); // Normalized Right-vector
memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector
aluNormalize(V); // Normalized Up-vector
memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector
aluNormalize(N); // Normalized At-vector
Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0];
Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1];
Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2];
aluMatrixVector(Position, Matrix);
//6. Apply filter gains and filters
switch(ALSource->DirectFilter.filter)
//5. Apply filter gains and filters
switch(ALSource->DirectFilter.type)
{
case AL_FILTER_LOWPASS:
DryMix *= ALSource->DirectFilter.Gain;
@@ -436,7 +475,7 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
break;
}
switch(ALSource->Send[0].WetFilter.filter)
switch(ALSource->Send[0].WetFilter.type)
{
case AL_FILTER_LOWPASS:
WetMix *= ALSource->Send[0].WetFilter.Gain;
@@ -454,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);
@@ -468,22 +508,25 @@ static ALvoid CalcSourceParams(ALCcontext *ALContext, ALsource *ALSource,
DryMix *= ListenerGain * ConeVolume;
WetMix *= ListenerGain;
//7. Convert normalized position into pannings, then into channel volumes
//6. Convert normalized position into pannings, then into channel volumes
aluNormalize(Position);
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? */
@@ -499,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:
@@ -581,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;
@@ -589,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;
@@ -604,6 +649,7 @@ ALvoid aluMixData(ALCcontext *ALContext,ALvoid *buffer,ALsizei size,ALenum forma
ALbufferlistitem *BufferListItem;
ALuint loop;
ALint64 DataSize64,DataPos64;
FILTER *Filter;
SuspendContext(ALContext);
@@ -622,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)
@@ -630,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;
@@ -662,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));
@@ -671,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++)
{
@@ -691,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);
}
}
@@ -700,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);
}
}
@@ -713,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
{
@@ -812,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
@@ -903,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];
@@ -941,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;
+16
View File
@@ -27,6 +27,11 @@
#include "alMain.h"
#ifdef _WIN32
#define _WIN32_IE 0x400
#include <shlobj.h>
#endif
typedef struct ConfigEntry {
char *key;
char *value;
@@ -201,6 +206,17 @@ void ReadALConfig(void)
cfgCount = 1;
#ifdef _WIN32
if(SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE)
{
int p = strlen(buffer);
snprintf(buffer+p, sizeof(buffer)-p, "\\alsoft.ini");
f = fopen(buffer, "rt");
if(f)
{
LoadConfigFromFile(f);
fclose(f);
}
}
#else
f = fopen("/etc/openal/alsoft.conf", "r");
if(!f)
+7 -2
View File
@@ -70,7 +70,13 @@ void DestroyRingBuffer(RingBuffer *ring)
ALsizei RingBufferSize(RingBuffer *ring)
{
return (ring->write_pos-ring->read_pos-1+ring->length) % ring->length;
ALsizei s;
EnterCriticalSection(&ring->cs);
s = (ring->write_pos-ring->read_pos-1+ring->length) % ring->length;
LeaveCriticalSection(&ring->cs);
return s;
}
void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
@@ -115,4 +121,3 @@ void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
LeaveCriticalSection(&ring->cs);
}
+9 -10
View File
@@ -28,8 +28,6 @@
#ifdef _WIN32
#include <windows.h>
typedef struct {
ALuint (*func)(ALvoid*);
ALvoid *ptr;
@@ -85,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;
@@ -116,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
+6 -4
View File
@@ -40,7 +40,7 @@ typedef struct {
ALvoid *buffer;
ALsizei size;
int killNow;
volatile int killNow;
ALvoid *thread;
} alsa_data;
@@ -595,6 +595,7 @@ static void alsa_close_capture(ALCdevice *pDevice)
static void alsa_start_capture(ALCdevice *pDevice)
{
alsa_data *data = (alsa_data*)pDevice->ExtraData;
psnd_pcm_prepare(data->pcmHandle);
psnd_pcm_start(data->pcmHandle);
}
@@ -856,6 +857,7 @@ next_card:
}
allCaptureDevNameMap[0].name = AppendCaptureDeviceList("ALSA Capture on default");
idx = 1;
while (card >= 0) {
sprintf(name, "hw:%d", card);
@@ -889,9 +891,9 @@ next_card:
dname = psnd_pcm_info_get_name(pcminfo);
snprintf(name, sizeof(name), "ALSA Capture on %s [%s]",
cname, dname);
allDevNameMap[idx].name = AppendCaptureDeviceList(name);
allDevNameMap[idx].card = card;
allDevNameMap[idx].dev = dev;
allCaptureDevNameMap[idx].name = AppendCaptureDeviceList(name);
allCaptureDevNameMap[idx].card = card;
allCaptureDevNameMap[idx].dev = dev;
idx++;
}
}
+28 -6
View File
@@ -20,6 +20,7 @@
#include "config.h"
#define _WIN32_WINNT 0x0500
#define INITGUID
#include <stdlib.h>
#include <stdio.h>
@@ -47,7 +48,7 @@ typedef struct {
LPDIRECTSOUNDBUFFER DSpbuffer;
LPDIRECTSOUNDBUFFER DSsbuffer;
int killNow;
volatile int killNow;
ALvoid *thread;
} DSoundData;
@@ -171,7 +172,25 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY);
if(SUCCEEDED(hr))
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
{
if(*(GetConfigValue(NULL, "format", "")) == 0)
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
else
{
if(device->Format == AL_FORMAT_MONO8 || device->Format == AL_FORMAT_MONO16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0);
else if(device->Format == AL_FORMAT_STEREO8 || device->Format == AL_FORMAT_STEREO16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, 0);
else if(device->Format == AL_FORMAT_QUAD8 || device->Format == AL_FORMAT_QUAD16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_QUAD, 0);
else if(device->Format == AL_FORMAT_51CHN8 || device->Format == AL_FORMAT_51CHN16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, 0);
else if(device->Format == AL_FORMAT_71CHN8 || device->Format == AL_FORMAT_71CHN16)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_7POINT1, 0);
else
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
}
}
if(SUCCEEDED(hr))
{
speakers = DSSPEAKER_CONFIG(speakers);
@@ -275,10 +294,13 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
if(SUCCEEDED(hr))
hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
device->ExtraData = pData;
pData->thread = StartThread(DSoundProc, device);
if(!pData->thread)
hr = E_FAIL;
if(SUCCEEDED(hr))
{
device->ExtraData = pData;
pData->thread = StartThread(DSoundProc, device);
if(!pData->thread)
hr = E_FAIL;
}
if(FAILED(hr))
{
+458
View File
@@ -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 ----------------- */
+1 -1
View File
@@ -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
View File
@@ -35,7 +35,7 @@ typedef struct {
ALvoid *buffer;
ALuint size;
int killNow;
volatile int killNow;
ALvoid *thread;
} wave_data;
+1
View File
@@ -20,6 +20,7 @@
#include "config.h"
#define _WIN32_WINNT 0x0500
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
+61 -23
View File
@@ -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)
@@ -22,13 +28,24 @@ OPTION(WINMM "Check for Windows Multimedia backend" ON)
OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON)
OPTION(WERROR "Treat compile warnings as errors" OFF)
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 "3")
SET(LIB_BUILD_VERSION "253")
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)
@@ -76,13 +93,6 @@ ELSE()
"Flags used by the compiler during debug builds."
FORCE)
# The mixer doesn't like GCC's strict aliasing optimizations. Make sure
# it's turned off
CHECK_C_COMPILER_FLAG(-fstrict-aliasing HAVE_STRICT_ALIASING)
IF("${HAVE_STRICT_ALIASING}")
ADD_DEFINITIONS(-fno-strict-aliasing)
ENDIF()
# Set visibility options if available
IF(NOT WIN32)
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
@@ -149,7 +159,7 @@ IF(DLOPEN)
ENDIF()
# Check if we have Windows headers
CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H)
CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0500)
IF(NOT HAVE_WINDOWS_H)
CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
IF(NOT HAVE_GETTIMEOFDAY)
@@ -167,6 +177,9 @@ IF(NOT HAVE_WINDOWS_H)
MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!")
ENDIF()
# Some systems need pthread_np.h to get recursive mutexes
CHECK_INCLUDE_FILES("pthread.h;pthread_np.h" HAVE_PTHREAD_NP_H)
# _GNU_SOURCE is needed on some systems for extra attributes, and
# _REENTRANT is needed for libc thread-safety
ADD_DEFINITIONS(-D_GNU_SOURCE=1 -D_REENTRANT)
@@ -180,7 +193,8 @@ ENDIF()
CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
IF(NOT HAVE_STDINT_H)
IF(HAVE_WINDOWS_H)
CHECK_C_SOURCE_COMPILES("\#include <windows.h>
CHECK_C_SOURCE_COMPILES("\#define _WIN32_WINNT 0x0500
\#include <windows.h>
__int64 foo;
int main() {return 0;}" HAVE___INT64)
ENDIF()
@@ -204,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
@@ -212,6 +225,7 @@ SET(ALC_OBJS Alc/ALc.c
Alc/alcRing.c
Alc/alcThread.c
Alc/bs2b.c
Alc/lpfilter.c
Alc/wave.c
)
@@ -264,7 +278,7 @@ IF(HAVE_WINDOWS_H)
ENDIF()
ENDIF()
IF(WINMM)
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H)
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500)
IF(HAVE_MMSYSTEM_H)
SET(HAVE_WINMM 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/winmm.c)
@@ -284,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})
@@ -310,16 +330,34 @@ 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_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
)
ENDIF()
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()
+4 -2
View File
@@ -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;
+1
View File
@@ -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;
+9
View File
@@ -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
+22 -11
View File
@@ -8,12 +8,18 @@
#ifdef _WIN32
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif
#include <windows.h>
#else
#include <assert.h>
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
#include <sys/time.h>
#include <time.h>
#include <errno.h>
@@ -42,6 +48,10 @@ static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
assert(ret == 0);
ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
#ifdef HAVE_PTHREAD_NP_H
if(ret != 0)
ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
#endif
assert(ret == 0);
ret = pthread_mutex_init(cs, &attrib);
assert(ret == 0);
@@ -93,20 +103,18 @@ static inline void Sleep(ALuint t)
extern "C" {
#endif
extern CRITICAL_SECTION _alMutex;
extern char _alDebug[256];
#define AL_PRINT(...) do { \
int _al_print_i; \
char *_al_print_fn = strrchr(__FILE__, '/'); \
if(!_al_print_fn) _al_print_fn = __FILE__; \
else _al_print_fn += 1; \
#define AL_PRINT(...) do { \
int _al_print_i; \
const char *_al_print_fn = strrchr(__FILE__, '/'); \
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__); \
if(_al_print_i < (int)sizeof(_alDebug) && _al_print_i > 0) \
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); \
_alDebug[sizeof(_alDebug)-1] = 0; \
fprintf(stderr, "%s", _alDebug); \
} while(0)
@@ -115,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*);
@@ -190,7 +201,7 @@ struct ALCcontext_struct
ALint lNumStereoSources;
ALCdevice *Device;
ALCchar ExtensionList[1024];
const ALCchar *ExtensionList;
struct bs2b *bs2b;
+4 -3
View File
@@ -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;
-74
View File
@@ -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
+3 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+11
View File
@@ -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}
+2 -1
View File
@@ -4,6 +4,7 @@
# specified.
# The system-wide settings can be put in /etc/openal/alsoft.conf and user-
# specific override settings in ~/.alsoftrc.
# For Windows, these settings should go into %AppData%\alsoft.ini
# Option and block names are case-insenstive. The supplied values are only
# hints and may not be honored (though generally it'll try to get as close as
@@ -37,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
+3
View File
@@ -46,4 +46,7 @@
/* Define if we have GCC's destructor attribute */
#cmakedefine HAVE_GCC_DESTRUCTOR
/* Define if we have pthread_np.h */
#cmakedefine HAVE_PTHREAD_NP_H
#endif
+171
View File
@@ -0,0 +1,171 @@
/*
* openal-info: Display information about ALC and AL.
*
* Idea based on glxinfo for OpenGL.
* Initial OpenAL version by Erik Hofman <erik@ehofman.com>.
* Further hacked by Sven Panne <sven.panne@aedion.de>.
* More work (clean up) by Chris Robinson <chris.kcat@gmail.com>.
*
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include "AL/alc.h"
#include "AL/al.h"
#include "AL/alext.h"
static const int indentation = 4;
static const int maxmimumWidth = 79;
static void printChar(int c, int *width)
{
putchar(c);
*width = ((c == '\n') ? 0 : ((*width) + 1));
}
static void indent(int *width)
{
int i;
for(i = 0; i < indentation; i++)
printChar(' ', width);
}
static void printExtensions(const char *header, char separator, const char *extensions)
{
int width = 0, start = 0, end = 0;
printf("%s:\n", header);
if(extensions == NULL || extensions[0] == '\0')
return;
indent(&width);
while (1)
{
if(extensions[end] == separator || extensions[end] == '\0')
{
if(width + end - start + 2 > maxmimumWidth)
{
printChar('\n', &width);
indent(&width);
}
while(start < end)
{
printChar(extensions[start], &width);
start++;
}
if(extensions[end] == '\0')
break;
start++;
end++;
if(extensions[end] == '\0')
break;
printChar(',', &width);
printChar(' ', &width);
}
end++;
}
printChar('\n', &width);
}
static void die(const char *kind, const char *description)
{
fprintf(stderr, "%s error %s occured\n", kind, description);
exit(EXIT_FAILURE);
}
static void checkForErrors(void)
{
{
ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
ALCenum error = alcGetError(device);
if(error != ALC_NO_ERROR)
die("ALC", (const char*)alcGetString(device, error));
}
{
ALenum error = alGetError();
if(error != AL_NO_ERROR)
die("AL", (const char*)alGetString(error));
}
}
static void printDevices(ALCenum which, const char *kind)
{
const char *s = alcGetString(NULL, which);
checkForErrors();
printf("Available %sdevices:\n", kind);
while(*s != '\0')
{
printf(" %s\n", s);
while(*s++ != '\0')
;
}
}
static void printALCInfo (void)
{
ALCint major, minor;
ALCdevice *device;
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE)
{
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATE_ALL_EXT") == AL_TRUE)
printDevices(ALC_ALL_DEVICES_SPECIFIER, "playback ");
else
printDevices(ALC_DEVICE_SPECIFIER, "playback ");
printDevices(ALC_CAPTURE_DEVICE_SPECIFIER, "capture ");
}
else
printf("No device enumeration available\n");
device = alcGetContextsDevice(alcGetCurrentContext());
checkForErrors();
printf("Default device: %s\n",
alcGetString(device, ALC_DEFAULT_DEVICE_SPECIFIER));
printf("Default capture device: %s\n",
alcGetString(device, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
checkForErrors();
printf("ALC version: %d.%d\n", (int)major, (int)minor);
printExtensions("ALC extensions", ' ',
alcGetString(device, ALC_EXTENSIONS));
checkForErrors();
}
static void printALInfo(void)
{
printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER));
printf("OpenAL version string: %s\n", alGetString(AL_VERSION));
printExtensions("OpenAL extensions", ' ', alGetString(AL_EXTENSIONS));
checkForErrors();
}
int main()
{
ALCdevice *device = alcOpenDevice(NULL);
ALCcontext *context = alcCreateContext(device, NULL);
alcMakeContextCurrent(context);
checkForErrors();
printALCInfo();
printALInfo();
checkForErrors();
alcMakeContextCurrent(NULL);
alcDestroyContext(context);
alcCloseDevice(device);
return EXIT_SUCCESS;
}
-5
View File
@@ -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
View File
@@ -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