Compare commits

...

125 Commits

Author SHA1 Message Date
Chris Robinson 342f639771 Release 1.2.218 2008-01-21 18:43:14 -08:00
Chris Robinson b5a2baafe5 Remove effect slot thunk entry when deallocated forcefully 2008-01-21 15:34:38 -08:00
Chris Robinson 781e4e5be4 Remove an unneceesary pointer check and decrease indentation 2008-01-21 14:54:15 -08:00
Chris Robinson f3dddb5e99 Remove unnecessary duplicate thunk lookups 2008-01-21 14:33:42 -08:00
Chris Robinson 9a5e892cad Small formatting updates 2008-01-20 22:16:28 -08:00
Chris Robinson 0317362662 Remove duplicate function 2008-01-20 19:22:39 -08:00
Chris Robinson 6b403a76e8 Don't access ALSource for every sample mix 2008-01-20 19:20:24 -08:00
Chris Robinson 6bf6c6fb7b More overflow protection 2008-01-20 13:27:54 -08:00
Chris Robinson 29618bee10 Prevent float samples from overflowing when converting to 16-bit 2008-01-20 00:43:02 -08:00
Chris Robinson db80f682c9 Clean a couple debug messages 2008-01-19 21:41:09 -08:00
Chris Robinson e1cdbac5a0 Close ALC first when exiting since devices might've been running when deleting stuff 2008-01-19 20:58:50 -08:00
Chris Robinson 543eb9d217 Don't use a multiple lists for extensions 2008-01-19 20:02:40 -08:00
Chris Robinson bc963463f3 Add an option for setting the max number of sources 2008-01-19 19:38:06 -08:00
Chris Robinson 86b7b3d54b Remove duplication of setting the max source count 2008-01-19 19:28:34 -08:00
Chris Robinson 799ba1f954 Use less ambiguous config file names 2008-01-19 18:18:14 -08:00
Chris Robinson 1a3e39e452 Remove some unnecessary duplicate math, which was making long lines 2008-01-19 00:49:05 -08:00
Chris Robinson 7dc73815ae Remove some branches 2008-01-18 21:39:09 -08:00
Chris Robinson 4caf2c7edd Implement AL_EFFECT_REVERB
Here is a quick description of how the reverb effect works:

 +--->---+*(4)
 |       V       new sample
 +-----+---+---+    |
 |extra|ltr|ref| <- +*(1)
 +-----+---+---+
   (3,5)*|   |*(2)
         +-->|
             V
         out sample

 1) Apply master reverb gain to incoming sample and place it at the head of the
    buffer. The master reverb gainhf was already applied when the source was
    initially mixed.
 2) Copy the delayed reflection sample to an output sample and apply the
    reflection gain.
 3) Apply the late reverb gain to the late reverb sample
 4) Copy the end of the buffer, applying a decay gain and the decay hf ratio,
    and add to the late reverb.
 5) Copy the late reverb sample, adding to the output sample.

 Then the head and sampling points are shifted forward, and done again for each
 new sample. The extra buffer length is determined by the Reverb Density
 property. A value of 0 gives a length of 0.1 seconds (long, with fairly
 distinct echos) , and 1 gives 0.075 seconds (short, indistinct echos).
 The decay gain is calculated such that after a number of loops to satisfy the
 Decay Time, a sample will be 1/32768th as powerful (virtually insignificant to
 the resulting output, and only getting further reduced). It is calculated as:

 DecayGain = pow(1.0f/32768.0f, 1.0/(DecayTime/ExtraLength));

 Things to note: Reverb Diffusion is not currently handled, nor is Decay HF
 Limit. Decay HF Ratios above 1 probably give incorrect results. Also, this
 method likely sucks, but it's the best I can come up with before release. :)
2008-01-18 21:25:40 -08:00
Chris Robinson 1b9d740244 Remove duplicated source freeing code 2008-01-18 00:56:01 -08:00
Chris Robinson 497ada9c77 Buffer size fixes. Partially reverts the ALSA buffer size "fix" 2008-01-18 00:28:25 -08:00
Chris Robinson 73e386dc6f Release effect slots when deleting sources 2008-01-17 21:17:08 -08:00
Chris Robinson 43cfc097de Don't dereference ALContext if there's no context yet
Patch by Evgeny A. Marchenko
2008-01-17 12:57:22 -08:00
Chris Robinson 6735fc7911 Add missing config.h includes 2008-01-16 14:09:04 -08:00
Chris Robinson be34dbe608 Don't include alAuxEffectSlot.h in alSource.h 2008-01-16 14:01:24 -08:00
Chris Robinson 70102e7cd3 Fix debug comments 2008-01-16 13:58:10 -08:00
Chris Robinson 8ad16145f6 Make sure sources are deleted with the context 2008-01-16 13:27:15 -08:00
Chris Robinson bb7b18d4e1 Keep track of references to effect slots, so they aren't deleted while in use 2008-01-16 13:20:09 -08:00
Chris Robinson 4742dedb45 Don't clamp wet gain if there's no send slot, and move slot gain calculation
To remove an extra if check
2008-01-16 13:00:35 -08:00
Chris Robinson 10a9bc62bf Store a reference to the effect slot in a source's send, not a copy 2008-01-16 12:43:25 -08:00
Chris Robinson 8cbbf17519 Allow getting and setting reverb parameters, as well as setting reverb effects
Reverb is still not implemented. The parameters just no-op for now.
2008-01-15 23:32:28 -08:00
Chris Robinson 24f433b938 Remove unneeded variables 2008-01-15 21:57:50 -08:00
Chris Robinson abc69dd3d0 Use acosf when available 2008-01-15 21:23:14 -08:00
Chris Robinson bf87aed459 Add reverb parameters 2008-01-15 20:32:20 -08:00
Chris Robinson 42306f93b3 Set default room rolloff factor 2008-01-15 19:59:19 -08:00
Chris Robinson 03ca50fa70 Use the previous low-pass filter again, as it seems to match the intended output better 2008-01-15 18:29:21 -08:00
Chris Robinson 7b1b8bd741 Set the default outer cone gainhf 2008-01-15 17:40:37 -08:00
Chris Robinson a11f25e47b Fix source and buffer out-of-memory conditions 2008-01-15 16:30:43 -08:00
Chris Robinson a6213ebfc7 Fix allocation of multiple effect slots, effects, and filters 2008-01-15 16:24:12 -08:00
Chris Robinson b95fcf5da1 Store effect slots in the context 2008-01-15 16:22:39 -08:00
Chris Robinson 707e596811 Don't append _struct to the effect slot struct name 2008-01-15 16:01:27 -08:00
Chris Robinson 5678041b92 Remove errant line 2008-01-15 15:53:58 -08:00
Chris Robinson 7f850d8fb0 Make sure a valid context is set for effect slots 2008-01-15 15:53:06 -08:00
Chris Robinson 7edc576e9c Fix some copy/paste errors 2008-01-15 15:37:54 -08:00
Chris Robinson 0041a09576 Move include so win32 gets it too, and remove unnecessary line 2008-01-15 12:45:24 -08:00
Chris Robinson 0f06254ecf Use a string for the detected backends, instead of a list 2008-01-15 12:43:43 -08:00
Chris Robinson ff5245ca8a Reword the backend options' text 2008-01-15 12:30:20 -08:00
Chris Robinson fe925ada59 Fix use of variables in checks 2008-01-15 12:25:51 -08:00
Chris Robinson b6596f38b9 Use CMAKE_BUILD_TYPE instead of custom options for compile modes 2008-01-15 10:00:56 -08:00
Chris Robinson 16fb3f6db5 Check for strncasecmp or _strnicmp 2008-01-14 16:30:18 -08:00
Chris Robinson a2e2522612 Let alIsExtensionPresent work with mixed-case extension names 2008-01-14 16:26:22 -08:00
Chris Robinson df07e8a65b Add support for AL_LOKI_quadriphonic 2008-01-14 16:11:15 -08:00
Chris Robinson 729f076c3b Reduce indentation 2008-01-14 15:38:15 -08:00
Chris Robinson dfc0118b8b Add an option for disabling ALSA mmap 2008-01-14 15:30:52 -08:00
Chris Robinson d9ef062caf Avoid busy waiting when waiting for suspend to clear 2008-01-14 13:23:49 -08:00
Chris Robinson 2b8ce3b4cf Let the mmap thread start the pcm stream when it's full
Instead of filling it with silence and starting it before the thread is active
2008-01-14 13:07:41 -08:00
Chris Robinson a27b855a39 Make sure the stream is playing when it's full 2008-01-14 12:59:44 -08:00
Chris Robinson 1634b69faf Don't restart the stream right after preparing it
It needs to be filled, first
2008-01-14 12:51:36 -08:00
Chris Robinson 59fa1f90d5 Don't attempt to recover the ALSA stream when filling silence
Since it was just prepared, any error would likely mean bigger problems
2008-01-14 12:49:21 -08:00
Chris Robinson e519338a2b Add missing stdio include 2008-01-14 10:55:13 -08:00
Chris Robinson 7a4870bd97 Close dangling devices when exiting 2008-01-14 10:54:33 -08:00
Chris Robinson a552e32a9a Destroy context if closing a device with one 2008-01-14 10:42:11 -08:00
Chris Robinson 29c6238b52 Keep track of open devices 2008-01-14 10:39:54 -08:00
Chris Robinson 38db8eb64b Reorder setting of some variables 2008-01-12 07:36:22 -08:00
Chris Robinson 3bbbf8a025 Merge branch 'master' into efx-experiment 2008-01-11 17:19:08 -08:00
Chris Robinson 978764cb6b Don't limit output wave filename size 2008-01-11 15:27:56 -08:00
Chris Robinson 893ecf1af2 Fix the Wave Writer's reliance on ftell
So output can work on FIFOs
2008-01-11 15:18:26 -08:00
Chris Robinson aa453b4e9e Use Sleep instead of usleep 2008-01-11 14:55:35 -08:00
Chris Robinson f8089d2026 Don't double-close a handle on error 2008-01-11 13:23:37 -08:00
Chris Robinson 40241b4e97 Don't attempt to open ALSA playback/capture if it didn't load 2008-01-11 13:00:30 -08:00
Chris Robinson f10408739e Add a wave file writing backend 2008-01-11 09:32:22 -08:00
Chris Robinson e1d0ad749b Use nanosleep instead of usleep
So not to rely on the non-standard unistd.h header
2008-01-11 08:15:44 -08:00
Chris Robinson 2a5a5b5c1b Add Sleep wrapper 2008-01-11 06:54:09 -08:00
Chris Robinson a97ecb8690 Add a timing wrapper, using gettimeofday 2008-01-11 06:01:51 -08:00
Chris Robinson bc56c00a9a Allow querying of ALC_MONO_SOURCES and ALC_STEREO_SOURCES
Based on a patch by Xavier Bouchoux
2008-01-10 08:24:23 -08:00
Chris Robinson 1e3ad2f9ce Use a more reliable thread loop for DSound, instead of a Win32 timer
Also use a simpler method for calculating the read/write location
2008-01-08 07:09:25 -08:00
Chris Robinson 9c97f07ec9 Remove unneeded silence field 2008-01-07 00:26:10 -08:00
Chris Robinson 312108a0d3 Try a different low-pass filter
Seems to be more correct, although it's not as powerful as the previous (which
may be a good thing)
2008-01-05 03:51:24 -08:00
Chris Robinson 5e48be27b8 Merge branch 'master' into efx-experiment 2008-01-04 14:40:38 -08:00
Chris Robinson 9ed574b399 Merge branch 'master' into efx-experiment 2008-01-01 06:29:11 -08:00
Chris Robinson 4e2f8e305e Fix wet volumes for multichannel path 2007-12-31 19:40:24 -08:00
Chris Robinson 3d78d93b40 Merge branch 'master' into efx-experiment 2007-12-31 19:34:52 -08:00
Chris Robinson 5a2f509104 Zero out wet send params when calculating source params
Instead of using a check in the mix loop
2007-12-31 19:13:18 -08:00
Chris Robinson d6288d63c6 Release the new stuff on exit for Windows, too 2007-12-22 13:18:05 -08:00
Chris Robinson 96bd020bd3 Use the right-channel sample... 2007-12-21 14:30:38 -08:00
Chris Robinson 8dc2aef058 Don't send stereo samples to the wet path without an auxiliary slot 2007-12-21 12:12:13 -08:00
Chris Robinson d43486f894 Fix extrenuous comment 2007-12-21 10:52:26 -08:00
Chris Robinson 229bc0d7e1 Merge branch 'master' into efx-experiment 2007-12-20 21:48:17 -08:00
Chris Robinson 7bf9ebf545 Allow auxiliary effect slot 0 when (un)setting the source auxiliary send 2007-12-18 23:51:21 -08:00
Chris Robinson 1e9302f564 Don't assume only one max send when setting source properties 2007-12-18 19:47:42 -08:00
Chris Robinson a433ae0ff4 Use the AuxSendAuto property of the effect slot 2007-12-18 19:43:54 -08:00
Chris Robinson e5609279da Implement AL_AUXILIARY_SEND_FILTER_GAIN_AUTO property 2007-12-18 19:13:41 -08:00
Chris Robinson afd3b71849 Implement AL_ROOM_ROLLOFF_FACTOR property 2007-12-18 19:03:40 -08:00
Chris Robinson 4cc64fa9a8 Don't allow properties on effect and filter name 0 2007-12-18 18:39:08 -08:00
Chris Robinson 7f55372727 Implement AL_EFFECT_TYPE property
Only the null effect type is accepted, right now
2007-12-18 18:15:52 -08:00
Chris Robinson 919b8c5bd1 Report one max auxiliary send per source 2007-12-18 18:13:49 -08:00
Chris Robinson a281027876 Implement AL_AUXILIARY_SEND_FILTER source property 2007-12-18 17:59:28 -08:00
Chris Robinson 72ce653bcf Remove unneeded struct member 2007-12-18 17:46:49 -08:00
Chris Robinson 17c8881444 Add AL_EFFECTSLOT_AUXILIARY_SEND_AUTO property (still unimplemented) 2007-12-18 17:41:44 -08:00
Chris Robinson 6aabc837a9 Fix initial WetMix setup 2007-12-18 17:21:13 -08:00
Chris Robinson 233e6f1765 Implement AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO property 2007-12-18 16:54:22 -08:00
Chris Robinson 9adc20e4e7 Implement AL_EFFECTSLOT_GAIN property 2007-12-18 15:47:24 -08:00
Chris Robinson bdf16bf601 Add initial auxiliary send paths 2007-12-18 15:10:21 -08:00
Chris Robinson cf03bfa156 Implement AL_EFFECTSLOT_EFFECT property 2007-12-18 14:22:59 -08:00
Chris Robinson d4f556836a Only allow one auxiliary effect slot 2007-12-18 13:42:13 -08:00
Chris Robinson ebb30ec5b0 Implement AL_AIR_ABSORPTION_FACTOR source property 2007-12-18 13:37:07 -08:00
Chris Robinson 168d8e3bee Add AL_FILTER_LOWPASS support
Direct filters only, since auxiliary sends and slots aren't available yet
2007-12-17 22:42:38 -08:00
Chris Robinson 654788f2cf Implement AL_CONE_OUTER_GAINHF source property 2007-12-17 21:56:31 -08:00
Chris Robinson 06f2076f04 Implement AL_DIRECT_FILTER_GAINHF_AUTO source property 2007-12-17 21:33:05 -08:00
Chris Robinson fc43a13927 Implement basic lowpass filter path 2007-12-17 21:00:52 -08:00
Chris Robinson 28f80fa113 Add AL_METERS_PER_UNIT listener property 2007-12-17 19:40:43 -08:00
Chris Robinson 9ebf1c1431 Don't attempt to free null effects or filters 2007-12-17 19:12:49 -08:00
Chris Robinson 8795932420 0 is a valid filter and effect name 2007-12-17 19:10:22 -08:00
Chris Robinson be50a5f992 Export ALC_EXT_EFX extension
Preliminary testing can now begin. Almost nothing will work, but the bare
framework is laid out, and the functions can begin to be implemented.
2007-12-17 18:01:01 -08:00
Chris Robinson 7086f5f84c Add new listener property definition 2007-12-17 17:55:27 -08:00
Chris Robinson 670487b4dd Add effect type enums 2007-12-17 17:52:03 -08:00
Chris Robinson 0ac746df57 Add new functions to proc address table 2007-12-17 17:44:11 -08:00
Chris Robinson 7458273634 Add auxiliary effect slot function skeletons 2007-12-17 17:43:19 -08:00
Chris Robinson aa386041e7 Fix comment 2007-12-17 17:20:55 -08:00
Chris Robinson 44e0fa9325 Implement effect function skeletons 2007-12-17 17:20:11 -08:00
Chris Robinson 91d214d713 Release left over filters on close 2007-12-17 17:08:44 -08:00
Chris Robinson 635f673b95 Implement ALC properties 2007-12-17 16:55:07 -08:00
Chris Robinson 35a82970a3 Implement AL_DIRECT_FILTER source property
Only AL_FILTER_NULL filter types are currently supported, however
2007-12-17 16:28:16 -08:00
Chris Robinson ac9bef0b31 Add EFX source filter properties 2007-12-17 16:02:34 -08:00
Chris Robinson f6bb6cc891 Add AL_FILTER_TYPE enum 2007-12-17 15:49:26 -08:00
Chris Robinson 56ff747463 Implement filter function skeletons 2007-12-17 15:43:35 -08:00
31 changed files with 3688 additions and 830 deletions
+155 -46
View File
@@ -26,12 +26,15 @@
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <ctype.h>
#include "alMain.h"
#include "alSource.h"
#include "AL/al.h"
#include "AL/alc.h"
#include "alThunk.h"
#include "alSource.h"
#include "alExtension.h"
#include "alAuxEffectSlot.h"
#include "bs2b.h"
///////////////////////////////////////////////////////
@@ -61,35 +64,27 @@ struct {
{ "winmm", alcWinMMInit, EmptyFuncs },
#endif
{ "wave", alc_wave_init, EmptyFuncs },
{ NULL, NULL, EmptyFuncs }
};
#undef EmptyFuncs
///////////////////////////////////////////////////////
#define ALC_EFX_MAJOR_VERSION 0x20001
#define ALC_EFX_MINOR_VERSION 0x20002
#define ALC_MAX_AUXILIARY_SENDS 0x20003
///////////////////////////////////////////////////////
// STRING and EXTENSIONS
typedef struct ALCextension_struct
{
ALCchar *extName;
ALvoid *address;
} ALCextension;
typedef struct ALCfunction_struct
{
ALCchar *funcName;
ALvoid *address;
} ALCfunction;
static ALCextension alcExtensions[] = {
{ "ALC_ENUMERATE_ALL_EXT", (ALvoid *) NULL },
{ "ALC_ENUMERATION_EXT", (ALvoid *) NULL },
{ "ALC_EXT_CAPTURE", (ALvoid *) NULL },
{ NULL, (ALvoid *) NULL }
};
static ALCfunction alcFunctions[] = {
{ "alcCreateContext", (ALvoid *) alcCreateContext },
{ "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
@@ -136,9 +131,14 @@ static ALenums enumeration[]={
{ (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
{ (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
{ (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
{ (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER },
{ (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
{ (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
// EFX Properties
{ (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
{ (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
{ (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
// ALC Error Message
{ (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
{ (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
@@ -166,16 +166,22 @@ static ALCchar *alcDefaultAllDeviceSpecifier = alcAllDeviceList;
static ALCchar *alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList;
static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE";
static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_EFX";
static ALCint alcMajorVersion = 1;
static ALCint alcMinorVersion = 1;
static ALCint alcEFXMajorVersion = 1;
static ALCint alcEFXMinorVersion = 0;
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
// Global Variables
static ALCdevice *g_pDeviceList = NULL;
static ALCuint g_ulDeviceCount = 0;
// Context List
static ALCcontext *g_pContextList = NULL;
static ALCuint g_ulContextCount = 0;
@@ -334,6 +340,7 @@ static ALvoid InitContext(ALCcontext *pContext)
//Initialise listener
pContext->Listener.Gain = 1.0f;
pContext->Listener.MetersPerUnit = 1.0f;
pContext->Listener.Position[0] = 0.0f;
pContext->Listener.Position[1] = 0.0f;
pContext->Listener.Position[2] = 0.0f;
@@ -363,7 +370,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");
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");
level = GetConfigValueInt(NULL, "cf_level", 0);
if(level > 0 && level <= 6)
@@ -382,26 +389,6 @@ static ALvoid InitContext(ALCcontext *pContext)
*/
static ALCvoid ExitContext(ALCcontext *pContext)
{
unsigned int i;
ALsource *ALSource;
ALsource *ALTempSource;
#ifdef _DEBUG
if (pContext->SourceCount>0)
AL_PRINT("alcDestroyContext() %d Source(s) NOT deleted\n", pContext->SourceCount);
#endif
// Free all the Sources still remaining
ALSource = pContext->Source;
for (i = 0; i < pContext->SourceCount; i++)
{
ALTempSource = ALSource->next;
ALTHUNK_REMOVEENTRY(ALSource->source);
memset(ALSource, 0, sizeof(ALsource));
free(ALSource);
ALSource = ALTempSource;
}
//Invalidate context
pContext->LastError = AL_NO_ERROR;
pContext->InUse = AL_FALSE;
@@ -452,6 +439,12 @@ ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, AL
pDevice->Funcs = &BackendList[i].Funcs;
if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
{
SuspendContext(NULL);
pDevice->next = g_pDeviceList;
g_pDeviceList = pDevice;
g_ulDeviceCount++;
ProcessContext(NULL);
DeviceFound = ALC_TRUE;
break;
}
@@ -475,9 +468,21 @@ ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, AL
ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
{
ALCboolean bReturn = ALC_FALSE;
ALCdevice **list;
if ((pDevice)&&(pDevice->IsCaptureDevice))
{
SuspendContext(NULL);
list = &g_pDeviceList;
while(*list != pDevice)
list = &(*list)->next;
*list = (*list)->next;
g_ulDeviceCount--;
ProcessContext(NULL);
ALCdevice_CloseCapture(pDevice);
free(pDevice);
@@ -685,13 +690,34 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
*data = alcMinorVersion;
break;
case ALC_EFX_MAJOR_VERSION:
if(!size)
SetALCError(ALC_INVALID_VALUE);
else
*data = alcEFXMajorVersion;
break;
case ALC_EFX_MINOR_VERSION:
if(!size)
SetALCError(ALC_INVALID_VALUE);
else
*data = alcEFXMinorVersion;
break;
case ALC_MAX_AUXILIARY_SENDS:
if(!size)
SetALCError(ALC_INVALID_VALUE);
else
*data = MAX_SENDS;
break;
case ALC_ATTRIBUTES_SIZE:
if(!device)
SetALCError(ALC_INVALID_DEVICE);
else if(!size)
SetALCError(ALC_INVALID_VALUE);
else
*data = 11;
*data = 12;
break;
case ALC_ALL_ATTRIBUTES:
@@ -713,13 +739,16 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
data[i++] = ALC_FALSE;
SuspendContext(NULL);
if(device->Context && size >= 11)
if(device->Context && size >= 12)
{
data[i++] = ALC_MONO_SOURCES;
data[i++] = device->Context->lNumMonoSources;
data[i++] = ALC_STEREO_SOURCES;
data[i++] = device->Context->lNumStereoSources;
data[i++] = ALC_MAX_AUXILIARY_SENDS;
data[i++] = MAX_SENDS;
}
ProcessContext(NULL);
@@ -754,6 +783,24 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
*data = ALC_FALSE;
break;
case ALC_MONO_SOURCES:
if(!device || !device->Context)
SetALCError(ALC_INVALID_DEVICE);
else if (size != 1)
SetALCError(ALC_INVALID_VALUE);
else
*data = device->Context->lNumMonoSources;
break;
case ALC_STEREO_SOURCES:
if(!device || !device->Context)
SetALCError(ALC_INVALID_DEVICE);
else if (size != 1)
SetALCError(ALC_INVALID_VALUE);
else
*data = device->Context->lNumStereoSources;
break;
default:
SetALCError(ALC_INVALID_ENUM);
break;
@@ -775,18 +822,31 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
{
ALCboolean bResult = ALC_FALSE;
ALsizei i = 0;
(void)device;
if (extName)
{
while(alcExtensions[i].extName &&
strcasecmp(alcExtensions[i].extName,extName) != 0)
i++;
const char *ptr;
size_t len;
if (alcExtensions[i].extName)
bResult = ALC_TRUE;
len = strlen(extName);
ptr = alcExtensionList;
while(ptr && *ptr)
{
if(strncasecmp(ptr, extName, len) == 0 &&
(ptr[len] == '\0' || isspace(ptr[len])))
{
bResult = ALC_TRUE;
break;
}
if((ptr=strchr(ptr, ' ')) != NULL)
{
do {
++ptr;
} while(isspace(*ptr));
}
}
}
else
SetALCError(ALC_INVALID_VALUE);
@@ -934,6 +994,9 @@ ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
// Lock context
SuspendContext(context);
ReleaseALSources(context);
ReleaseALAuxiliaryEffectSlots(context);
context->Device->Context = NULL;
list = &g_pContextList;
@@ -1089,9 +1152,13 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
device->FrameSize = aluBytesFromFormat(device->Format) *
device->Channels;
device->UpdateFreq = GetConfigValueInt(NULL, "refresh", 0);
device->UpdateFreq = GetConfigValueInt(NULL, "refresh", 8192);
if((ALint)device->UpdateFreq <= 0)
device->UpdateFreq = 8192 * device->Frequency / 22050;
device->UpdateFreq = 8192;
device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
if((ALint)device->MaxNoOfSources <= 0)
device->MaxNoOfSources = 256;
// Find a playback device to open
for(i = 0;BackendList[i].Init;i++)
@@ -1099,6 +1166,12 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
device->Funcs = &BackendList[i].Funcs;
if(ALCdevice_OpenPlayback(device, deviceName))
{
SuspendContext(NULL);
device->next = g_pDeviceList;
g_pDeviceList = device;
g_ulDeviceCount++;
ProcessContext(NULL);
bDeviceFound = AL_TRUE;
break;
}
@@ -1124,9 +1197,23 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
{
ALCboolean bReturn = ALC_FALSE;
ALCdevice **list;
if ((pDevice)&&(!pDevice->IsCaptureDevice))
{
SuspendContext(NULL);
list = &g_pDeviceList;
while(*list != pDevice)
list = &(*list)->next;
*list = (*list)->next;
g_ulDeviceCount--;
ProcessContext(NULL);
if(pDevice->Context)
alcDestroyContext(pDevice->Context);
ALCdevice_ClosePlayback(pDevice);
//Release device structure
@@ -1140,4 +1227,26 @@ ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
return bReturn;
}
ALCvoid ReleaseALC(ALCvoid)
{
ALCdevice *Dev;
#ifdef _DEBUG
if(g_ulContextCount > 0)
AL_PRINT("exit() %u device(s) and %u context(s) NOT deleted\n", g_ulDeviceCount, g_ulContextCount);
#endif
while(g_pDeviceList)
{
Dev = g_pDeviceList;
g_pDeviceList = g_pDeviceList->next;
if(Dev->IsCaptureDevice)
alcCaptureCloseDevice(Dev);
else
alcCloseDevice(Dev);
}
}
///////////////////////////////////////////////////////
+687 -504
View File
File diff suppressed because it is too large Load Diff
+19 -2
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
@@ -200,7 +202,14 @@ void ReadALConfig(void)
#ifdef _WIN32
#else
f = fopen("/etc/openal/config", "r");
f = fopen("/etc/openal/alsoft.conf", "r");
if(!f)
{
f = fopen("/etc/openal/config", "r");
if(f)
AL_PRINT("Reading /etc/openal/config; this file is deprecated\n"
"\tPlease rename it to /etc/openal/alsoft.conf\n");
}
if(f)
{
LoadConfigFromFile(f);
@@ -208,8 +217,16 @@ void ReadALConfig(void)
}
if(getenv("HOME") && *(getenv("HOME")))
{
snprintf(buffer, sizeof(buffer), "%s/.openalrc", getenv("HOME"));
snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", getenv("HOME"));
f = fopen(buffer, "r");
if(!f)
{
snprintf(buffer, sizeof(buffer), "%s/.openalrc", getenv("HOME"));
f = fopen(buffer, "r");
if(f)
AL_PRINT("Reading ~/.openalrc; this file is deprecated\n"
"\tPlease rename it to ~/.alsoftrc\n");
}
if(f)
{
LoadConfigFromFile(f);
+2 -2
View File
@@ -18,11 +18,11 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include "config.h"
#include "alMain.h"
+2
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include "alMain.h"
+48 -85
View File
@@ -67,6 +67,7 @@ MAKE_FUNC(snd_pcm_hw_params_set_rate_near);
MAKE_FUNC(snd_pcm_hw_params_set_rate);
MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near);
MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min);
MAKE_FUNC(snd_pcm_hw_params_get_period_size);
MAKE_FUNC(snd_pcm_hw_params_get_access);
MAKE_FUNC(snd_pcm_hw_params);
MAKE_FUNC(snd_pcm_prepare);
@@ -108,20 +109,16 @@ static int xrun_recovery(snd_pcm_t *handle, int err)
if (err == -EPIPE)
{ /* under-run */
err = psnd_pcm_prepare(handle);
if(err >= 0)
err = psnd_pcm_start(handle);
if (err < 0)
AL_PRINT("prepare failed: %s\n", psnd_strerror(err));
}
else if (err == -ESTRPIPE)
{
while ((err = psnd_pcm_resume(handle)) == -EAGAIN)
usleep(1); /* wait until the suspend flag is released */
Sleep(1); /* wait until the suspend flag is released */
if (err < 0)
{
err = psnd_pcm_prepare(handle);
if(err >= 0)
err = psnd_pcm_start(handle);
if (err < 0)
AL_PRINT("prepare failed: %s\n", psnd_strerror(err));
}
@@ -177,7 +174,18 @@ static ALuint ALSAProc(ALvoid *ptr)
// make sure there's frames to process
if(avail == 0)
{
usleep(1000);
if(state != SND_PCM_STATE_RUNNING)
{
err = psnd_pcm_start(data->pcmHandle);
if(err < 0)
err = xrun_recovery(data->pcmHandle, err);
if(err < 0)
{
AL_PRINT("start failed: %s\n", psnd_strerror(err));
break;
}
}
Sleep(1);
continue;
}
@@ -239,9 +247,8 @@ static ALuint ALSANoMMapProc(ALvoid *ptr)
case -EAGAIN:
continue;
case -ESTRPIPE:
do {
ret = psnd_pcm_resume(data->pcmHandle);
} while(ret == -EAGAIN);
while((ret=psnd_pcm_resume(data->pcmHandle)) == -EAGAIN)
Sleep(1);
break;
case -EPIPE:
break;
@@ -265,55 +272,6 @@ static ALuint ALSANoMMapProc(ALvoid *ptr)
return 0;
}
static void fill_silence(snd_pcm_t *pcmHandle, snd_pcm_format_t alsaFormat, int channels)
{
const snd_pcm_channel_area_t *areas = NULL;
snd_pcm_sframes_t avail, commitres;
snd_pcm_uframes_t offset, frames;
int err;
avail = psnd_pcm_avail_update(pcmHandle);
if(avail < 0)
{
err = xrun_recovery(pcmHandle, avail);
if (err < 0)
{
AL_PRINT("available update failed: %s\n", psnd_strerror(err));
return;
}
}
// it is possible that contiguous areas are smaller, thus we use a loop
while (avail > 0)
{
frames = avail;
err = psnd_pcm_mmap_begin(pcmHandle, &areas, &offset, &frames);
if (err < 0)
{
err = xrun_recovery(pcmHandle, err);
if (err < 0)
{
AL_PRINT("mmap begin error: %s\n", psnd_strerror(err));
break;
}
continue;
}
psnd_pcm_areas_silence(areas, offset, channels, frames, alsaFormat);
commitres = psnd_pcm_mmap_commit(pcmHandle, offset, frames);
if (commitres < 0 || (commitres-frames) != 0)
{
AL_PRINT("mmap commit error: %s\n",
psnd_strerror(commitres >= 0 ? -EPIPE : commitres));
break;
}
avail -= frames;
}
}
static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
snd_pcm_uframes_t bufferSizeInFrames;
@@ -322,9 +280,14 @@ static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceNam
unsigned int periods;
alsa_data *data;
char driver[64];
const char *str;
int allowmmap;
char *err;
int i;
if(!alsa_handle)
return ALC_FALSE;
strncpy(driver, GetConfigValue("alsa", "device", "default"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
if(deviceName)
@@ -364,7 +327,7 @@ open_alsa:
i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if(i < 0)
{
usleep(200000);
Sleep(200);
i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
}
if(i >= 0)
@@ -393,24 +356,28 @@ open_alsa:
AL_PRINT("Unknown format?! %x\n", device->Format);
}
periods = GetConfigValueInt("alsa", "periods", 4);
if((int)periods <= 0)
periods = 4;
bufferSizeInFrames = device->UpdateFreq / periods;
periods = GetConfigValueInt("alsa", "periods", 0);
bufferSizeInFrames = device->UpdateFreq;
str = GetConfigValue("alsa", "mmap", "true");
allowmmap = (strcasecmp(str, "true") == 0 ||
strcasecmp(str, "yes") == 0 ||
strcasecmp(str, "on") == 0 ||
atoi(str) != 0);
psnd_pcm_hw_params_malloc(&p);
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
/* start with the largest configuration space possible */
if(!(ok(psnd_pcm_hw_params_any(data->pcmHandle, p), "any") &&
/* set interleaved access */
(ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access") ||
((allowmmap && ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access")) ||
ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED), "set access")) &&
/* set format (implicitly sets sample bits) */
ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, data->format), "set format") &&
/* set channels (implicitly sets frame bits) */
ok(psnd_pcm_hw_params_set_channels(data->pcmHandle, p, device->Channels), "set channels") &&
/* set periods (implicitly constrains period/buffer parameters) */
ok(psnd_pcm_hw_params_set_periods_near(data->pcmHandle, p, &periods, NULL), "set periods near") &&
(!periods || ok(psnd_pcm_hw_params_set_periods_near(data->pcmHandle, p, &periods, NULL), "set periods near")) &&
/* set rate (implicitly constrains period/buffer parameters) */
ok(psnd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &device->Frequency, NULL), "set rate near") &&
/* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
@@ -435,9 +402,17 @@ open_alsa:
return ALC_FALSE;
}
if((i=psnd_pcm_hw_params_get_period_size(p, &bufferSizeInFrames, NULL)) < 0)
{
AL_PRINT("get_period_size failed: %s\n", psnd_strerror(i));
psnd_pcm_hw_params_free(p);
psnd_pcm_close(data->pcmHandle);
free(data);
return ALC_FALSE;
}
psnd_pcm_hw_params_free(p);
device->MaxNoOfSources = 256;
device->UpdateFreq = bufferSizeInFrames;
data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, device->UpdateFreq);
@@ -463,18 +438,6 @@ open_alsa:
free(data);
return ALC_FALSE;
}
fill_silence(data->pcmHandle, data->format, device->Channels);
i = psnd_pcm_start(data->pcmHandle);
if(i < 0)
{
AL_PRINT("start error: %s\n", psnd_strerror(i));
psnd_pcm_close(data->pcmHandle);
free(data->buffer);
free(data);
return ALC_FALSE;
}
}
device->ExtraData = data;
@@ -511,13 +474,15 @@ static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceNam
{
snd_pcm_format_t alsaFormat;
snd_pcm_hw_params_t *p;
unsigned int periods = 4;
snd_pcm_uframes_t bufferSizeInFrames;
alsa_data *data;
char driver[64];
char *err;
int i;
if(!alsa_handle)
return ALC_FALSE;
strncpy(driver, GetConfigValue("alsa", "capture", "default"), sizeof(driver)-1);
driver[sizeof(driver)-1] = 0;
if(deviceName)
@@ -546,7 +511,7 @@ open_alsa:
i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
if(i < 0)
{
usleep(200000);
Sleep(200);
i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
}
if(i >= 0)
@@ -575,7 +540,7 @@ open_alsa:
AL_PRINT("Unknown format?! %x\n", format);
}
bufferSizeInFrames = SampleSize / periods;
bufferSizeInFrames = SampleSize;
psnd_pcm_hw_params_malloc(&p);
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
@@ -587,8 +552,6 @@ open_alsa:
ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, alsaFormat), "set format") &&
/* set channels (implicitly sets frame bits) */
ok(psnd_pcm_hw_params_set_channels(data->pcmHandle, p, pDevice->Channels), "set channels") &&
/* set periods (implicitly constrains period/buffer parameters) */
ok(psnd_pcm_hw_params_set_periods_near(data->pcmHandle, p, &periods, NULL), "set periods near") &&
/* set rate (implicitly constrains period/buffer parameters) */
ok(psnd_pcm_hw_params_set_rate(data->pcmHandle, p, frequency, 0), "set rate") &&
/* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
@@ -758,7 +721,7 @@ void alc_alsa_init(BackendFuncs *func_list)
} while(0)
#else
str = NULL;
alsa_handle = NULL;
alsa_handle = 0xDEADBEEF;
#define LOAD_FUNC(f) p##f = f
#endif
@@ -778,6 +741,7 @@ LOAD_FUNC(snd_pcm_hw_params_set_rate_near);
LOAD_FUNC(snd_pcm_hw_params_set_rate);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near);
LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min);
LOAD_FUNC(snd_pcm_hw_params_get_period_size);
LOAD_FUNC(snd_pcm_hw_params_get_access);
LOAD_FUNC(snd_pcm_hw_params);
LOAD_FUNC(snd_pcm_prepare);
@@ -893,7 +857,6 @@ next_card:
}
if (err >= 0 && (err = psnd_ctl_card_info(handle, info)) < 0) {
AL_PRINT("control hardware info (%i): %s\n", card, psnd_strerror(err));
psnd_ctl_close(handle);
}
else if (err >= 0 && card < MAX_DEVICES-1)
{
+2
View File
@@ -21,6 +21,8 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <math.h>
#include "bs2b.h"
+68 -72
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
@@ -36,71 +38,74 @@ typedef struct {
LPDIRECTSOUND lpDS;
LPDIRECTSOUNDBUFFER DSpbuffer;
LPDIRECTSOUNDBUFFER DSsbuffer;
MMRESULT ulDSTimerID;
DWORD OldWriteCursor;
int killNow;
ALvoid *thread;
} DSoundData;
static ALCchar *DeviceList[16];
static void CALLBACK DirectSoundProc(UINT uID,UINT uReserved,DWORD_PTR dwUser,DWORD_PTR dwReserved1,DWORD_PTR dwReserved2)
static ALuint DSoundProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice *)dwUser;
DSoundData *pData = pDevice->ExtraData;
DWORD PlayCursor,WriteCursor;
BYTE *WritePtr1,*WritePtr2;
DWORD WriteCnt1,WriteCnt2;
WAVEFORMATEX OutputType;
DWORD BytesPlayed;
DWORD BufSize;
HRESULT DSRes;
ALCdevice *pDevice = (ALCdevice*)ptr;
DSoundData *pData = (DSoundData*)pDevice->ExtraData;
DWORD LastCursor = 0;
DWORD PlayCursor;
VOID *WritePtr;
DWORD WriteCnt;
DWORD avail;
HRESULT err;
(void)uID;
(void)uReserved;
(void)dwReserved1;
(void)dwReserved2;
BufSize = pDevice->UpdateFreq * 2 * pDevice->FrameSize;
// Get current play and write cursors
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer,&PlayCursor,&WriteCursor);
if (!pData->OldWriteCursor) pData->OldWriteCursor=WriteCursor-PlayCursor;
// Get the output format and figure the number of bytes played (block aligned)
IDirectSoundBuffer_GetFormat(pData->DSsbuffer,&OutputType,sizeof(WAVEFORMATEX),NULL);
BytesPlayed=((((WriteCursor<pData->OldWriteCursor)?(BufSize+WriteCursor-pData->OldWriteCursor):(WriteCursor-pData->OldWriteCursor))/OutputType.nBlockAlign)*OutputType.nBlockAlign);
// Lock output buffer started at 40msec in front of the old write cursor (15msec in front of the actual write cursor)
DSRes=IDirectSoundBuffer_Lock(pData->DSsbuffer,(pData->OldWriteCursor+(OutputType.nSamplesPerSec/25)*OutputType.nBlockAlign)%BufSize,BytesPlayed,(LPVOID*)&WritePtr1,&WriteCnt1,(LPVOID*)&WritePtr2,&WriteCnt2,0);
// If the buffer is lost, restore it, play and lock
if (DSRes==DSERR_BUFFERLOST)
while(!pData->killNow)
{
IDirectSoundBuffer_Restore(pData->DSsbuffer);
IDirectSoundBuffer_Play(pData->DSsbuffer,0,0,DSBPLAY_LOOPING);
DSRes=IDirectSoundBuffer_Lock(pData->DSsbuffer,(pData->OldWriteCursor+(OutputType.nSamplesPerSec/25)*OutputType.nBlockAlign)%BufSize,BytesPlayed,(LPVOID*)&WritePtr1,&WriteCnt1,(LPVOID*)&WritePtr2,&WriteCnt2,0);
// Get current play and write cursors
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
avail = (PlayCursor-LastCursor) % (pDevice->UpdateFreq*pDevice->FrameSize);
if(avail == 0)
{
Sleep(1);
continue;
}
// Lock output buffer
WriteCnt = 0;
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr, &WriteCnt, NULL, NULL, 0);
// If the buffer is lost, restore it, play and lock
if(err == DSERR_BUFFERLOST)
{
err = IDirectSoundBuffer_Restore(pData->DSsbuffer);
if(SUCCEEDED(err))
err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
if(SUCCEEDED(err))
err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, (LPVOID*)&WritePtr, &WriteCnt, NULL, NULL, 0);
}
// Successfully locked the output buffer
if(SUCCEEDED(err))
{
// If we have an active context, mix data directly into output buffer otherwise fill with silence
SuspendContext(NULL);
aluMixData(pDevice->Context, WritePtr, WriteCnt, pDevice->Format);
ProcessContext(NULL);
// Unlock output buffer only when successfully locked
IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr, WriteCnt, NULL, 0);
}
else
AL_PRINT("Buffer lock error: %#lx\n", err);
// Update old write cursor location
LastCursor += WriteCnt;
LastCursor %= pDevice->UpdateFreq*pDevice->FrameSize;
}
// Successfully locked the output buffer
if (DSRes==DS_OK)
{
// If we have an active context, mix data directly into output buffer otherwise fill with silence
SuspendContext(NULL);
if (WritePtr1)
aluMixData(pDevice->Context, WritePtr1, WriteCnt1, pDevice->Format);
if (WritePtr2)
aluMixData(pDevice->Context, WritePtr2, WriteCnt2, pDevice->Format);
ProcessContext(NULL);
// Unlock output buffer only when successfully locked
IDirectSoundBuffer_Unlock(pData->DSsbuffer,WritePtr1,WriteCnt1,WritePtr2,WriteCnt2);
}
// Update old write cursor location
pData->OldWriteCursor=((pData->OldWriteCursor+BytesPlayed)%BufSize);
return 0;
}
static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
{
DSBUFFERDESC DSBDescription;
@@ -169,7 +174,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
DSBDescription.dwBufferBytes=device->UpdateFreq * 2 * device->FrameSize;
DSBDescription.dwBufferBytes=device->UpdateFreq * device->FrameSize;
DSBDescription.lpwfxFormat=&OutputType;
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
}
@@ -177,6 +182,11 @@ 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(FAILED(hr))
{
if (pData->DSsbuffer)
@@ -190,10 +200,6 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
return ALC_FALSE;
}
pData->ulDSTimerID = timeSetEvent(25, 0, (LPTIMECALLBACK)DirectSoundProc, (DWORD)device, (UINT)TIME_CALLBACK_FUNCTION|TIME_PERIODIC);
device->MaxNoOfSources = 256;
device->ExtraData = pData;
return ALC_TRUE;
}
@@ -201,26 +207,16 @@ static void DSoundClosePlayback(ALCdevice *device)
{
DSoundData *pData = device->ExtraData;
// Stop and release the DS timer
if (pData->ulDSTimerID)
timeKillEvent(pData->ulDSTimerID);
pData->killNow = 1;
StopThread(pData->thread);
// Wait ... just in case any timer events happen
Sleep(100);
SuspendContext(NULL);
if (pData->DSsbuffer)
IDirectSoundBuffer_Release(pData->DSsbuffer);
if (pData->DSpbuffer)
IDirectSoundBuffer_Release(pData->DSpbuffer);
IDirectSoundBuffer_Release(pData->DSsbuffer);
IDirectSoundBuffer_Release(pData->DSpbuffer);
IDirectSound_Release(pData->lpDS);
//Deinit COM
CoUninitialize();
ProcessContext(NULL);
free(pData);
device->ExtraData = NULL;
}
+4 -9
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -55,7 +57,6 @@ typedef struct {
ALubyte *mix_data;
int data_size;
int silence;
RingBuffer *ring;
int doCapture;
@@ -106,7 +107,7 @@ static ALuint OSSProc(ALvoid *ptr)
memmove(data->mix_data, data->mix_data+wrote, remaining);
}
else
usleep(1000);
Sleep(1);
}
return 0;
@@ -132,7 +133,7 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
}
if(amt == 0)
{
usleep(1000);
Sleep(1);
continue;
}
if(data->doCapture)
@@ -181,11 +182,9 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
switch(aluBytesFromFormat(device->Format))
{
case 1:
data->silence = 0x80;
ossFormat = AFMT_U8;
break;
case 2:
data->silence = 0;
ossFormat = AFMT_S16_NE;
break;
default:
@@ -243,8 +242,6 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
data->data_size = device->UpdateFreq * device->FrameSize;
data->mix_data = calloc(1, data->data_size);
device->MaxNoOfSources = 256;
device->ExtraData = data;
data->thread = StartThread(OSSProc, device);
if(data->thread == NULL)
@@ -311,11 +308,9 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName,
switch(aluBytesFromFormat(format))
{
case 1:
data->silence = 0x80;
ossFormat = AFMT_U8;
break;
case 2:
data->silence = 0;
ossFormat = AFMT_S16_NE;
break;
default:
+334
View File
@@ -0,0 +1,334 @@
/**
* 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 <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "alMain.h"
#include "AL/al.h"
#include "AL/alc.h"
typedef struct {
FILE *f;
long DataStart;
ALvoid *buffer;
ALuint size;
int killNow;
ALvoid *thread;
} wave_data;
static ALCchar *waveDevice;
static ALuint WaveProc(ALvoid *ptr)
{
ALCdevice *pDevice = (ALCdevice*)ptr;
wave_data *data = (wave_data*)pDevice->ExtraData;
ALuint frameSize;
ALuint now, last;
size_t WriteCnt;
ALuint avail;
union {
short s;
char b[sizeof(short)];
} uSB;
uSB.s = 1;
frameSize = aluBytesFromFormat(pDevice->Format) *
aluChannelsFromFormat(pDevice->Format);
last = timeGetTime();
while(!data->killNow)
{
now = timeGetTime();
avail = (now-last) * pDevice->Frequency / 1000;
if(avail < pDevice->UpdateFreq/4)
{
Sleep(1);
continue;
}
while(avail > 0)
{
SuspendContext(NULL);
WriteCnt = min(data->size, avail);
aluMixData(pDevice->Context, data->buffer, WriteCnt * frameSize,
pDevice->Format);
ProcessContext(NULL);
if(uSB.b[0] != 1 && aluBytesFromFormat(pDevice->Format) > 1)
{
ALubyte *bytes = data->buffer;
ALuint i;
for(i = 0;i < WriteCnt*frameSize;i++)
fputc(bytes[i^1], data->f);
}
else
fwrite(data->buffer, frameSize, WriteCnt, data->f);
if(ferror(data->f))
{
AL_PRINT("Error writing to file\n");
data->killNow = 1;
break;
}
avail -= WriteCnt;
}
last = now;
}
return 0;
}
static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
{
wave_data *data;
ALuint channels;
ALuint bits;
const char *fname;
int i;
fname = GetConfigValue("wave", "file", "");
if(!fname[0])
return ALC_FALSE;
if(deviceName)
{
if(strcmp(deviceName, waveDevice) != 0)
return ALC_FALSE;
device->szDeviceName = waveDevice;
}
else
device->szDeviceName = waveDevice;
data = (wave_data*)calloc(1, sizeof(wave_data));
data->f = fopen(fname, "wb");
if(!data->f)
{
free(data);
AL_PRINT("Could not open file '%s': %s\n", fname, strerror(errno));
return ALC_FALSE;
}
bits = aluBytesFromFormat(device->Format) * 8;
channels = aluChannelsFromFormat(device->Format);
switch(bits)
{
case 8:
case 16:
if(channels == 0)
{
AL_PRINT("Unknown format?! %x\n", device->Format);
fclose(data->f);
free(data);
return ALC_FALSE;
}
break;
default:
AL_PRINT("Unknown format?! %x\n", device->Format);
fclose(data->f);
free(data);
return ALC_FALSE;
}
fprintf(data->f, "RIFF");
fputc(0, data->f); // 'RIFF' header len; filled in at close
fputc(0, data->f);
fputc(0, data->f);
fputc(0, data->f);
fprintf(data->f, "WAVE");
fprintf(data->f, "fmt ");
fputc(16, data->f); // 'fmt ' header len; 16 bytes for PCM
fputc(0, data->f);
fputc(0, data->f);
fputc(0, data->f);
// 16-bit val, format type id (PCM: 1)
fputc(1, data->f);
fputc(0, data->f);
// 16-bit val, channel count
fputc(channels&0xff, data->f);
fputc((channels>>8)&0xff, data->f);
// 32-bit val, frequency
fputc(device->Frequency&0xff, data->f);
fputc((device->Frequency>>8)&0xff, data->f);
fputc((device->Frequency>>16)&0xff, data->f);
fputc((device->Frequency>>24)&0xff, data->f);
// 32-bit val, bytes per second
i = device->Frequency * channels * bits / 8;
fputc(i&0xff, data->f);
fputc((i>>8)&0xff, data->f);
fputc((i>>16)&0xff, data->f);
fputc((i>>24)&0xff, data->f);
// 16-bit val, frame size
i = channels * bits / 8;
fputc(i&0xff, data->f);
fputc((i>>8)&0xff, data->f);
// 16-bit val, bits per sample
fputc(bits&0xff, data->f);
fputc((bits>>8)&0xff, data->f);
fprintf(data->f, "data");
fputc(0, data->f); // 'data' header len; filled in at close
fputc(0, data->f);
fputc(0, data->f);
fputc(0, data->f);
if(ferror(data->f))
{
AL_PRINT("Error writing header: %s\n", strerror(errno));
fclose(data->f);
free(data);
return ALC_FALSE;
}
data->DataStart = ftell(data->f);
device->UpdateFreq = max(device->UpdateFreq, 2048);
data->size = device->UpdateFreq;
data->buffer = malloc(data->size * channels * bits / 8);
if(!data->buffer)
{
AL_PRINT("buffer malloc failed\n");
fclose(data->f);
free(data);
return ALC_FALSE;
}
device->ExtraData = data;
data->thread = StartThread(WaveProc, device);
if(data->thread == NULL)
{
device->ExtraData = NULL;
fclose(data->f);
free(data->buffer);
free(data);
return ALC_FALSE;
}
return ALC_TRUE;
}
static void wave_close_playback(ALCdevice *device)
{
wave_data *data = (wave_data*)device->ExtraData;
ALuint dataLen;
long size;
data->killNow = 1;
StopThread(data->thread);
size = ftell(data->f);
if(size > 0)
{
dataLen = size - data->DataStart;
if(fseek(data->f, data->DataStart-4, SEEK_SET) == 0)
{
fputc(dataLen&0xff, data->f); // 'data' header len
fputc((dataLen>>8)&0xff, data->f);
fputc((dataLen>>16)&0xff, data->f);
fputc((dataLen>>24)&0xff, data->f);
}
if(fseek(data->f, 4, SEEK_SET) == 0)
{
size -= 8;
fputc(size&0xff, data->f); // 'WAVE' header len
fputc((size>>8)&0xff, data->f);
fputc((size>>16)&0xff, data->f);
fputc((size>>24)&0xff, data->f);
}
}
fclose(data->f);
free(data->buffer);
free(data);
device->ExtraData = NULL;
}
static ALCboolean wave_open_capture(ALCdevice *pDevice, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
{
(void)pDevice;
(void)deviceName;
(void)frequency;
(void)format;
(void)SampleSize;
return ALC_FALSE;
}
static void wave_close_capture(ALCdevice *pDevice)
{
(void)pDevice;
}
static void wave_start_capture(ALCdevice *pDevice)
{
(void)pDevice;
}
static void wave_stop_capture(ALCdevice *pDevice)
{
(void)pDevice;
}
static void wave_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
{
(void)pDevice;
(void)pBuffer;
(void)lSamples;
}
static ALCuint wave_available_samples(ALCdevice *pDevice)
{
(void)pDevice;
return 0;
}
BackendFuncs wave_funcs = {
wave_open_playback,
wave_close_playback,
wave_open_capture,
wave_close_capture,
wave_start_capture,
wave_stop_capture,
wave_capture_samples,
wave_available_samples
};
void alc_wave_init(BackendFuncs *func_list)
{
*func_list = wave_funcs;
waveDevice = AppendDeviceList("Wave File Writer");
AppendAllDeviceList(waveDevice);
}
+2
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
+92 -56
View File
@@ -15,21 +15,19 @@ PROJECT(OpenAL)
SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
OPTION(ALSA "ALSA backend" ON)
OPTION(OSS "OSS backend" ON)
OPTION(DSOUND "DirectSound backend" ON)
OPTION(WINMM "Windows Multimedia backend" ON)
OPTION(ALSA "Check for ALSA backend" ON)
OPTION(OSS "Check for OSS backend" ON)
OPTION(DSOUND "Check for DirectSound backend" ON)
OPTION(WINMM "Check for Windows Multimedia backend" ON)
OPTION(DLOPEN "Use the dlopen API for loading optional libs" ON)
OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON)
OPTION(DEBUG "Build lib in debug mode" OFF)
OPTION(NODEBUG "Disable all debug info for optimizations" OFF)
OPTION(WERROR "Treat compile warnings as errors" OFF)
SET(LIB_MAJOR_VERSION "1")
SET(LIB_MINOR_VERSION "1")
SET(LIB_BUILD_VERSION "93")
SET(LIB_MINOR_VERSION "2")
SET(LIB_BUILD_VERSION "218")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
@@ -42,8 +40,18 @@ CHECK_TYPE_SIZE("void*" SIZEOF_VOIDP)
# Add definitions, compiler switches, etc.
INCLUDE_DIRECTORIES(OpenAL32/Include include "${OpenAL_BINARY_DIR}")
IF("${MSVC}")
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
FORCE)
ENDIF()
IF(MSVC)
# ???
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -D_DEBUG")
SET(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DNDEBUG")
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
ELSE()
ADD_DEFINITIONS(-Wall)
CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA)
@@ -55,13 +63,18 @@ ELSE()
ADD_DEFINITIONS(-Werror)
ENDIF()
IF(DEBUG)
ADD_DEFINITIONS(-g3)
ELSEIF(NODEBUG)
ADD_DEFINITIONS(-O2 -funroll-loops -fomit-frame-pointer)
ELSE()
ADD_DEFINITIONS(-g -O2 -funroll-loops)
ENDIF()
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -funroll-loops -D_DEBUG" CACHE STRING
"Flags used by the compiler during Release with Debug Info builds."
FORCE)
SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING
"Flags used by the compiler during release minsize builds."
FORCE)
SET(CMAKE_C_FLAGS_RELEASE "-O2 -funroll-loops -fomit-frame-pointer -DNDEBUG" CACHE STRING
"Flags used by the compiler during release builds"
FORCE)
SET(CMAKE_C_FLAGS_DEBUG "-g3 -D_DEBUG" CACHE STRING
"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
@@ -71,7 +84,7 @@ ELSE()
ENDIF()
# Set visibility options if available
IF(NOT "${WIN32}")
IF(NOT WIN32)
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
@@ -86,32 +99,38 @@ ELSE()
ENDIF()
ENDIF()
IF(DEBUG)
ADD_DEFINITIONS(-D_DEBUG)
ELSEIF(NODEBUG)
ADD_DEFINITIONS(-DNDEBUG)
ENDIF()
CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF)
IF("${HAVE_SQRTF}")
CHECK_LIBRARY_EXISTS(m acosf "" HAVE_ACOSF)
IF(HAVE_SQRTF OR HAVE_ACOSF)
SET(EXTRA_LIBS m ${EXTRA_LIBS})
ENDIF()
CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
IF(NOT "${HAVE_STRCASECMP}")
IF(NOT HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
IF(NOT "${HAVE__STRICMP}")
IF(NOT HAVE__STRICMP)
MESSAGE(FATAL_ERROR "No case-insensitive compare function found, please report!")
ENDIF()
ADD_DEFINITIONS(-Dstrcasecmp=_stricmp)
ENDIF()
CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP)
IF(NOT HAVE_STRNCASECMP)
CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP)
IF(NOT HAVE__STRNICMP)
MESSAGE(FATAL_ERROR "No case-insensitive size-limitted compare function found, please report!")
ENDIF()
ADD_DEFINITIONS(-Dstrncasecmp=_strnicmp)
ENDIF()
CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF)
IF(NOT "${HAVE_SNPRINTF}")
IF(NOT HAVE_SNPRINTF)
CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF)
IF(NOT "${HAVE__SNPRINTF}")
IF(NOT HAVE__SNPRINTF)
MESSAGE(FATAL_ERROR "No snprintf function found, please report!")
ENDIF()
@@ -121,9 +140,9 @@ ENDIF()
# Check for the dlopen API (for dynamicly loading backend libs)
IF(DLOPEN)
CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H)
IF("${HAVE_DLFCN_H}")
IF(HAVE_DLFCN_H)
CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_LIBDL)
IF("${HAVE_LIBDL}")
IF(HAVE_LIBDL)
SET(EXTRA_LIBS dl ${EXTRA_LIBS})
ENDIF()
ENDIF()
@@ -131,10 +150,20 @@ ENDIF()
# Check if we have Windows headers
CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H)
IF(NOT "${HAVE_WINDOWS_H}")
IF(NOT HAVE_WINDOWS_H)
CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
IF(NOT HAVE_GETTIMEOFDAY)
MESSAGE(FATAL_ERROR "No timing function found!")
ENDIF()
CHECK_FUNCTION_EXISTS(nanosleep HAVE_NANOSLEEP)
IF(NOT HAVE_NANOSLEEP)
MESSAGE(FATAL_ERROR "No sleep function found!")
ENDIF()
# We need pthreads outside of Windows
CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
IF(NOT "${HAVE_PTHREAD_H}")
IF(NOT HAVE_PTHREAD_H)
MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!")
ENDIF()
@@ -142,22 +171,22 @@ IF(NOT "${HAVE_WINDOWS_H}")
# _REENTRANT is needed for libc thread-safety
ADD_DEFINITIONS(-D_GNU_SOURCE=1 -D_REENTRANT)
CHECK_LIBRARY_EXISTS(pthread pthread_create "" HAVE_LIBPTHREAD)
IF("${HAVE_LIBPTHREAD}")
IF(HAVE_LIBPTHREAD)
SET(EXTRA_LIBS pthread ${EXTRA_LIBS})
ENDIF()
ENDIF()
# Check for a 64-bit type
CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
IF(NOT "${HAVE_STDINT_H}")
IF("${HAVE_WINDOWS_H}")
IF(NOT HAVE_STDINT_H)
IF(HAVE_WINDOWS_H)
CHECK_C_SOURCE_COMPILES("\#include <windows.h>
__int64 foo;
int main() {return 0;}" HAVE___INT64)
ENDIF()
IF(NOT "${HAVE___INT64}")
IF(NOT "${SIZEOF_LONG}" MATCHES "8")
IF(NOT "${SIZEOF_LONG_LONG}" MATCHES "8")
IF(NOT HAVE___INT64)
IF(NOT SIZEOF_LONG MATCHES "8")
IF(NOT SIZEOF_LONG_LONG MATCHES "8")
MESSAGE(FATAL_ERROR "No 64-bit types found, please report!")
ENDIF()
ENDIF()
@@ -165,9 +194,12 @@ IF(NOT "${HAVE_STDINT_H}")
ENDIF()
SET(OPENAL_OBJS OpenAL32/alBuffer.c
SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
OpenAL32/alBuffer.c
OpenAL32/alEffect.c
OpenAL32/alError.c
OpenAL32/alExtension.c
OpenAL32/alFilter.c
OpenAL32/alListener.c
OpenAL32/alSource.c
OpenAL32/alState.c
@@ -180,6 +212,7 @@ SET(ALC_OBJS Alc/ALc.c
Alc/alcRing.c
Alc/alcThread.c
Alc/bs2b.c
Alc/wave.c
)
SET(BACKENDS "")
@@ -187,15 +220,15 @@ SET(BACKENDS "")
# Check ALSA backend
IF(ALSA)
CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ALSA_ASOUNDLIB_H)
IF("${HAVE_ALSA_ASOUNDLIB_H}")
IF(HAVE_ALSA_ASOUNDLIB_H)
CHECK_LIBRARY_EXISTS(asound snd_pcm_open "" HAVE_LIBASOUND)
IF("${HAVE_DLFCN_H}" OR "${HAVE_LIBASOUND}")
IF(HAVE_DLFCN_H OR HAVE_LIBASOUND)
SET(HAVE_ALSA 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/alsa.c)
IF("${HAVE_DLFCN_H}")
SET(BACKENDS ${BACKENDS} ALSA)
IF(HAVE_DLFCN_H)
SET(BACKENDS "${BACKENDS} ALSA,")
ELSE()
SET(BACKENDS ${BACKENDS} ALSA\(linked\))
SET(BACKENDS "${BACKENDS} ALSA \(linked\),")
SET(EXTRA_LIBS asound ${EXTRA_LIBS})
ENDIF()
ENDIF()
@@ -205,54 +238,57 @@ ENDIF()
# Check OSS backend
IF(OSS)
CHECK_INCLUDE_FILE(sys/soundcard.h HAVE_SYS_SOUNDCARD_H)
IF("${HAVE_SYS_SOUNDCARD_H}")
IF(HAVE_SYS_SOUNDCARD_H)
SET(HAVE_OSS 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/oss.c)
SET(BACKENDS ${BACKENDS} OSS)
SET(BACKENDS "${BACKENDS} OSS,")
ENDIF()
ENDIF()
# Check DSound/MMSystem backend
IF("${HAVE_WINDOWS_H}")
IF(HAVE_WINDOWS_H)
SET(CMAKE_REQUIRED_LIBRARIES ole32)
CHECK_C_SOURCE_COMPILES("int main() {return 0;}" HAVE_LIBOLE32)
SET(CMAKE_REQUIRED_LIBRARIES "")
# CHECK_LIBRARY_EXISTS(ole32 CoInitialize "" HAVE_LIBOLE32)
IF("${HAVE_LIBOLE32}")
IF(HAVE_LIBOLE32)
SET(EXTRA_LIBS ole32 ${EXTRA_LIBS})
ENDIF()
IF(DSOUND)
CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H)
IF("${HAVE_DSOUND_H}")
IF(HAVE_DSOUND_H)
SET(HAVE_DSOUND 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/dsound.c)
SET(BACKENDS ${BACKENDS} DirectSound)
SET(BACKENDS "${BACKENDS} DirectSound,")
CHECK_LIBRARY_EXISTS(dxguid IID_IDirectSound "" HAVE_LIBDXGUID)
IF("${HAVE_LIBDXGUID}")
IF(HAVE_LIBDXGUID)
SET(EXTRA_LIBS dxguid ${EXTRA_LIBS})
ENDIF()
ENDIF()
ENDIF()
IF(WINMM)
CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H)
IF("${HAVE_MMSYSTEM_H}")
IF(HAVE_MMSYSTEM_H)
SET(HAVE_WINMM 1)
SET(ALC_OBJS ${ALC_OBJS} Alc/winmm.c)
SET(BACKENDS ${BACKENDS} WinMM)
SET(BACKENDS "${BACKENDS} WinMM,")
SET(CMAKE_REQUIRED_LIBRARIES winmm)
CHECK_C_SOURCE_COMPILES("int main() {return 0;}" HAVE_LIBWINMM)
SET(CMAKE_REQUIRED_LIBRARIES "")
# CHECK_LIBRARY_EXISTS(winmm waveInOpen "" HAVE_LIBWINMM)
IF("${HAVE_LIBWINMM}")
IF(HAVE_LIBWINMM)
SET(EXTRA_LIBS winmm ${EXTRA_LIBS})
ENDIF()
ENDIF()
ENDIF()
ENDIF()
# This is always available
SET(BACKENDS "${BACKENDS} WaveFile")
# End configuration
CONFIGURE_FILE(
"${OpenAL_SOURCE_DIR}/config.h.in"
@@ -261,7 +297,7 @@ CONFIGURE_FILE(
ADD_DEFINITIONS(-DAL_BUILD_LIBRARY)
# Build a shared library
IF("${WIN32}")
IF(WIN32)
SET(LIBNAME openal32)
ELSE()
SET(LIBNAME openal)
@@ -270,7 +306,7 @@ ENDIF()
ADD_LIBRARY(${LIBNAME} SHARED ${OPENAL_OBJS} ${ALC_OBJS})
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION}
SOVERSION ${LIB_MAJOR_VERSION})
IF("${WIN32}")
IF(WIN32)
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
ENDIF()
+61
View File
@@ -0,0 +1,61 @@
#ifndef _AL_AUXEFFECTSLOT_H_
#define _AL_AUXEFFECTSLOT_H_
#include "alEffect.h"
#include "AL/al.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AL_EFFECTSLOT_EFFECT 0x0001
#define AL_EFFECTSLOT_GAIN 0x0002
#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003
#define AL_EFFECTSLOT_NULL 0x0000
typedef struct ALeffectslot
{
ALeffect effect;
ALfloat Gain;
ALboolean AuxSendAuto;
ALfloat *ReverbBuffer;
// in frames!
ALuint ReverbLength;
ALuint ReverbPos;
ALuint ReverbReflectPos;
ALuint ReverbLatePos;
ALfloat ReverbDecayGain;
ALfloat LastDecaySample;
ALuint refcount;
// Index to itself
ALuint effectslot;
struct ALeffectslot *next;
} ALeffectslot;
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots);
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues);
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
#ifdef __cplusplus
}
#endif
#endif
+89
View File
@@ -0,0 +1,89 @@
#ifndef _AL_EFFECT_H_
#define _AL_EFFECT_H_
#include "AL/al.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AL_EFFECT_TYPE 0x8001
#define AL_EFFECT_NULL 0x0000
#define AL_EFFECT_REVERB 0x0001
#define AL_EFFECT_CHORUS 0x0002
#define AL_EFFECT_DISTORTION 0x0003
#define AL_EFFECT_ECHO 0x0004
#define AL_EFFECT_FLANGER 0x0005
#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006
#define AL_EFFECT_VOCAL_MORPHER 0x0007
#define AL_EFFECT_PITCH_SHIFTER 0x0008
#define AL_EFFECT_RING_MODULATOR 0x0009
#define AL_EFFECT_AUTOWAH 0x000A
#define AL_EFFECT_COMPRESSOR 0x000B
#define AL_EFFECT_EQUALIZER 0x000C
#define AL_REVERB_DENSITY 0x0001
#define AL_REVERB_DIFFUSION 0x0002
#define AL_REVERB_GAIN 0x0003
#define AL_REVERB_GAINHF 0x0004
#define AL_REVERB_DECAY_TIME 0x0005
#define AL_REVERB_DECAY_HFRATIO 0x0006
#define AL_REVERB_REFLECTIONS_GAIN 0x0007
#define AL_REVERB_REFLECTIONS_DELAY 0x0008
#define AL_REVERB_LATE_REVERB_GAIN 0x0009
#define AL_REVERB_LATE_REVERB_DELAY 0x000A
#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
#define AL_REVERB_DECAY_HFLIMIT 0x000D
typedef struct ALeffect_struct
{
// Effect type (AL_EFFECT_NULL, ...)
ALenum type;
struct {
ALfloat Density;
ALfloat Diffusion;
ALfloat Gain;
ALfloat GainHF;
ALfloat DecayTime;
ALfloat DecayHFRatio;
ALfloat ReflectionsGain;
ALfloat ReflectionsDelay;
ALfloat LateReverbGain;
ALfloat LateReverbDelay;
ALfloat AirAbsorptionGainHF;
ALfloat RoomRolloffFactor;
ALboolean DecayHFLimit;
} Reverb;
// Index to itself
ALuint effect;
struct ALeffect_struct *next;
} ALeffect;
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects);
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects);
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect);
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues);
ALvoid ReleaseALEffects(ALvoid);
#ifdef __cplusplus
}
#endif
#endif
+55
View File
@@ -0,0 +1,55 @@
#ifndef _AL_FILTER_H_
#define _AL_FILTER_H_
#include "AL/al.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AL_FILTER_TYPE 0x8001
#define AL_FILTER_NULL 0x0000
#define AL_FILTER_LOWPASS 0x0001
#define AL_FILTER_HIGHPASS 0x0002
#define AL_FILTER_BANDPASS 0x0003
#define AL_LOWPASS_GAIN 0x0001
#define AL_LOWPASS_GAINHF 0x0002
typedef struct ALfilter_struct
{
// Filter type (AL_FILTER_NULL, ...)
ALenum type;
ALfloat Gain;
ALfloat GainHF;
// Index to itself
ALuint filter;
struct ALfilter_struct *next;
} ALfilter;
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters);
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters);
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter);
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue);
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue);
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue);
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues);
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue);
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues);
ALvoid ReleaseALFilters(ALvoid);
#ifdef __cplusplus
}
#endif
#endif
+3
View File
@@ -7,6 +7,8 @@
extern "C" {
#endif
#define AL_METERS_PER_UNIT 0x20004
typedef struct ALlistener_struct
{
ALfloat Position[3];
@@ -14,6 +16,7 @@ typedef struct ALlistener_struct
ALfloat Forward[3];
ALfloat Up[3];
ALfloat Gain;
ALfloat MetersPerUnit;
} ALlistener;
#ifdef __cplusplus
+41 -1
View File
@@ -2,17 +2,21 @@
#define AL_MAIN_H
#include <string.h>
#include <stdio.h>
#include "alu.h"
#ifdef _WIN32
#include <windows.h>
//#define strcasecmp _stricmp
#else
#include <assert.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#define IsBadWritePtr(a,b) (0)
@@ -52,6 +56,30 @@ static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
assert(ret == 0);
}
/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed
* to the expected DWORD. Both are defined as unsigned 32-bit types, however.
* Additionally, Win32 is supposed to measure the time since Windows started,
* as opposed to the actual time. */
static inline ALuint timeGetTime(void)
{
struct timeval tv;
int ret;
ret = gettimeofday(&tv, NULL);
assert(ret == 0);
return tv.tv_usec/1000 + tv.tv_sec*1000;
}
static inline void Sleep(ALuint t)
{
struct timespec tv, rem;
tv.tv_nsec = (t*1000000)%1000000000;
tv.tv_sec = t/1000;
while(nanosleep(&tv, &rem) == -1 && errno == EINTR)
tv = rem;
}
#define min(x,y) (((x)<(y))?(x):(y))
#define max(x,y) (((x)>(y))?(x):(y))
#endif
@@ -86,6 +114,9 @@ extern char _alDebug[256];
#define AL_FORMAT_MONO_IMA4 0x1300
#define AL_FORMAT_STEREO_IMA4 0x1301
#define AL_FORMAT_QUAD8_LOKI 0x10004
#define AL_FORMAT_QUAD16_LOKI 0x10005
#define AL_FORMAT_51CHN8 0x120A
#define AL_FORMAT_51CHN16 0x120B
#define AL_FORMAT_51CHN32 0x120C
@@ -105,6 +136,7 @@ extern char _alDebug[256];
#define SWMIXER_OUTPUT_RATE 44100
#define SPEEDOFSOUNDMETRESPERSEC (343.3f)
#define AIRABSORBGAINHF (0.994f)
typedef struct {
ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
@@ -122,6 +154,7 @@ void alc_alsa_init(BackendFuncs *func_list);
void alc_oss_init(BackendFuncs *func_list);
void alcDSoundInit(BackendFuncs *func_list);
void alcWinMMInit(BackendFuncs *FuncList);
void alc_wave_init(BackendFuncs *func_list);
struct ALCdevice_struct
@@ -145,6 +178,8 @@ struct ALCdevice_struct
BackendFuncs *Funcs;
void *ExtraData; // For the backend's use
ALCdevice *next;
};
#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b)))
@@ -163,6 +198,9 @@ struct ALCcontext_struct
struct ALsource *Source;
ALuint SourceCount;
struct ALeffectslot *AuxiliaryEffectSlot;
ALuint AuxiliaryEffectSlotCount;
ALenum LastError;
ALboolean InUse;
@@ -185,6 +223,8 @@ struct ALCcontext_struct
ALCcontext *next;
};
ALCvoid ReleaseALC(ALCvoid);
ALCchar *AppendDeviceList(char *name);
ALCchar *AppendAllDeviceList(char *name);
ALCchar *AppendCaptureDeviceList(char *name);
+34
View File
@@ -3,8 +3,21 @@
#define AL_NUM_SOURCE_PARAMS 128
/* This cannot be changed without working on the code! */
#define MAX_SENDS 1
#include "alFilter.h"
#include "AL/al.h"
#define AL_DIRECT_FILTER 0x20005
#define AL_AUXILIARY_SEND_FILTER 0x20006
#define AL_AIR_ABSORPTION_FACTOR 0x20007
#define AL_ROOM_ROLLOFF_FACTOR 0x20008
#define AL_CONE_OUTER_GAINHF 0x20009
#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A
#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B
#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C
#ifdef __cplusplus
extern "C" {
#endif
@@ -50,6 +63,25 @@ typedef struct ALsource
ALuint BuffersPlayed; // Number of buffers played on this loop
ALuint BufferPosition; // Read position in audio data of current buffer
ALfilter DirectFilter;
struct {
struct ALeffectslot *Slot;
ALfilter WetFilter;
} Send[MAX_SENDS];
ALfloat LastDrySample;
ALfloat LastWetSample;
ALboolean DryGainHFAuto;
ALboolean WetGainAuto;
ALboolean WetGainHFAuto;
ALfloat OuterGainHF;
ALfloat AirAbsorptionFactor;
ALfloat RoomRolloffFactor;
// Index to itself
ALuint source;
@@ -64,6 +96,8 @@ typedef struct ALsource
struct ALsource *next;
} ALsource;
ALvoid ReleaseALSources(ALCcontext *Context);
#ifdef __cplusplus
}
#endif
+11
View File
@@ -18,8 +18,13 @@
* 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;
@@ -37,7 +42,10 @@ BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
break;
case DLL_PROCESS_DETACH:
ReleaseALC();
ReleaseALBuffers();
ReleaseALEffects();
ReleaseALFilters();
FreeALConfig();
ALTHUNK_EXIT();
DeleteCriticalSection(&_alMutex);
@@ -54,7 +62,10 @@ static void my_deinit()
if(once) return;
once = AL_TRUE;
ReleaseALC();
ReleaseALBuffers();
ReleaseALEffects();
ReleaseALFilters();
FreeALConfig();
ALTHUNK_EXIT();
DeleteCriticalSection(&_alMutex);
+537
View File
@@ -0,0 +1,537 @@
/**
* 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 <stdlib.h>
#include <math.h>
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#include "alAuxEffectSlot.h"
#include "alThunk.h"
#include "alError.h"
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
ALCcontext *Context;
ALsizei i;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (n > 0)
{
/* NOTE: We only support one slot currently */
if(n == 1 && Context->AuxiliaryEffectSlotCount == 0)
{
// Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
{
ALeffectslot **list = &Context->AuxiliaryEffectSlot;
while(*list)
list = &(*list)->next;
i = 0;
while(i < n)
{
*list = calloc(1, sizeof(ALeffectslot));
if(!(*list))
{
// We must have run out or memory
alDeleteAuxiliaryEffectSlots(i, effectslots);
alSetError(AL_OUT_OF_MEMORY);
break;
}
(*list)->Gain = 1.0;
(*list)->AuxSendAuto = AL_TRUE;
(*list)->refcount = 0;
effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->effectslot = effectslots[i];
Context->AuxiliaryEffectSlotCount++;
i++;
list = &(*list)->next;
}
}
}
else
alSetError(AL_INVALID_OPERATION);
}
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
ALCcontext *Context;
ALeffectslot *ALAuxiliaryEffectSlot;
ALsizei i;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (n >= 0)
{
// Check that all effectslots are valid
for (i = 0; i < n; i++)
{
if (!alIsAuxiliaryEffectSlot(effectslots[i]))
{
alSetError(AL_INVALID_NAME);
break;
}
else
{
ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
if(ALAuxiliaryEffectSlot->refcount > 0)
{
alSetError(AL_INVALID_NAME);
break;
}
}
}
if (i == n)
{
// All effectslots are valid
for (i = 0; i < n; i++)
{
// Recheck that the effectslot is valid, because there could be duplicated names
if (alIsAuxiliaryEffectSlot(effectslots[i]))
{
ALeffectslot **list;
ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
// Remove Source from list of Sources
list = &Context->AuxiliaryEffectSlot;
while(*list && *list != ALAuxiliaryEffectSlot)
list = &(*list)->next;
if(*list)
*list = (*list)->next;
ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
free(ALAuxiliaryEffectSlot->ReverbBuffer);
memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
free(ALAuxiliaryEffectSlot);
Context->AuxiliaryEffectSlotCount--;
}
}
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
}
AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
{
ALCcontext *Context;
ALeffectslot **list;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return AL_FALSE;
}
SuspendContext(Context);
list = &Context->AuxiliaryEffectSlot;
while(*list && (*list)->effectslot != effectslot)
list = &(*list)->next;
ProcessContext(Context);
return (*list ? AL_TRUE : AL_FALSE);
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
switch(param)
{
case AL_EFFECTSLOT_EFFECT:
if(alIsEffect(iValue))
{
ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
InitializeEffect(Context, ALEffectSlot, effect);
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
if(iValue == AL_TRUE || iValue == AL_FALSE)
ALEffectSlot->AuxSendAuto = iValue;
else
alSetError(AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
switch(param)
{
case AL_EFFECTSLOT_EFFECT:
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
switch(param)
{
case AL_EFFECTSLOT_GAIN:
if(flValue >= 0.0f && flValue <= 1.0f)
ALEffectSlot->Gain = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
switch(param)
{
case AL_EFFECTSLOT_GAIN:
alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
switch(param)
{
case AL_EFFECTSLOT_EFFECT:
*piValue = ALEffectSlot->effect.effect;
break;
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
*piValue = ALEffectSlot->AuxSendAuto;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
switch(param)
{
case AL_EFFECTSLOT_EFFECT:
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
alGetAuxiliaryEffectSloti(effectslot, param, piValues);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
switch(param)
{
case AL_EFFECTSLOT_GAIN:
*pflValue = ALEffectSlot->Gain;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
if(!Context)
{
alSetError(AL_INVALID_OPERATION);
return;
}
SuspendContext(Context);
if (alIsAuxiliaryEffectSlot(effectslot))
{
switch(param)
{
case AL_EFFECTSLOT_GAIN:
alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
{
ALfloat *ptr = NULL;
if(!effect)
{
memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
goto done;
}
if(effect->type == AL_EFFECT_REVERB)
{
ALuint size;
ALfloat reverbwait;
reverbwait = (1.0f-effect->Reverb.Density)*(0.1f-0.075f) + 0.075f;
size = (ALuint)((ALfloat)Context->Frequency *
(effect->Reverb.ReflectionsDelay +
effect->Reverb.LateReverbDelay +
reverbwait)) + 1;
ptr = calloc(size, sizeof(ALfloat));
if(!ptr)
{
alSetError(AL_OUT_OF_MEMORY);
return;
}
ALEffectSlot->ReverbLength = size;
ALEffectSlot->ReverbPos = 0;
ALEffectSlot->ReverbReflectPos = (ALuint)(ALEffectSlot->ReverbLength -
((ALfloat)Context->Frequency *
effect->Reverb.ReflectionsDelay)) %
ALEffectSlot->ReverbLength;
ALEffectSlot->ReverbLatePos = (ALuint)(ALEffectSlot->ReverbLength -
((ALfloat)Context->Frequency *
(effect->Reverb.LateReverbDelay +
effect->Reverb.ReflectionsDelay))) %
ALEffectSlot->ReverbLength;
ALEffectSlot->ReverbDecayGain = pow(1.0/32768.0, 1.0/(effect->Reverb.DecayTime/reverbwait));
}
memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
done:
free(ALEffectSlot->ReverbBuffer);
ALEffectSlot->ReverbBuffer = ptr;
}
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
{
#ifdef _DEBUG
if(Context->AuxiliaryEffectSlotCount > 0)
AL_PRINT("alcDestroyContext(): %d AuxiliaryEffectSlot(s) NOT deleted\n", Context->AuxiliaryEffectSlotCount);
#endif
while(Context->AuxiliaryEffectSlot)
{
ALeffectslot *temp = Context->AuxiliaryEffectSlot;
Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
// Release effectslot structure
free(temp->ReverbBuffer);
ALTHUNK_REMOVEENTRY(temp->effectslot);
memset(temp, 0, sizeof(ALeffectslot));
free(temp);
}
Context->AuxiliaryEffectSlotCount = 0;
}
+31 -14
View File
@@ -20,6 +20,8 @@
#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
@@ -95,20 +97,20 @@ ALAPI ALvoid ALAPIENTRY alGenBuffers(ALsizei n,ALuint *puiBuffers)
while(i < n)
{
*list = calloc(1, sizeof(ALbuffer));
if(*list)
if(!(*list))
{
puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->state = UNUSED;
g_uiBufferCount++;
i++;
list = &(*list)->next;
alDeleteBuffers(i, puiBuffers);
alSetError(AL_OUT_OF_MEMORY);
break;
}
}
// If we didn't create all the Buffers, we must have run out of memory
if (i != n)
alSetError(AL_OUT_OF_MEMORY);
puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->state = UNUSED;
g_uiBufferCount++;
i++;
list = &(*list)->next;
}
}
else
{
@@ -369,12 +371,19 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
if (ALBuf->data)
{
ALint smp;
for (i = 0;i < size;i+=4)
{
ALBuf->data[i+0] = 0;
ALBuf->data[i+1] = 0;
ALBuf->data[i+2] = (ALshort)(((ALfloat*)data)[i/2+0] * 32767.5f - 0.5);
ALBuf->data[i+3] = (ALshort)(((ALfloat*)data)[i/2+1] * 32767.5f - 0.5);
smp = (((ALfloat*)data)[i/2+0] * 32767.5f - 0.5);
smp = min(smp, 32767);
smp = max(smp, -32768);
ALBuf->data[i+2] = (ALshort)smp;
smp = (((ALfloat*)data)[i/2+1] * 32767.5f - 0.5);
smp = min(smp, 32767);
smp = max(smp, -32768);
ALBuf->data[i+3] = (ALshort)smp;
}
memset(&(ALBuf->data[size]), 0, 16*NewChannels);
@@ -392,6 +401,8 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
}
} break;
case AL_FORMAT_QUAD8_LOKI:
case AL_FORMAT_QUAD16_LOKI:
case AL_FORMAT_QUAD8:
case AL_FORMAT_QUAD16:
case AL_FORMAT_QUAD32:
@@ -1046,8 +1057,14 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
ALBuf->data = realloc(ALBuf->data, (8*NewChannels + size) * (1*sizeof(ALshort)));
if (ALBuf->data)
{
ALint smp;
for (i = 0;i < size;i++)
ALBuf->data[i] = (ALshort)(((ALfloat*)data)[i] * 32767.5f - 0.5);
{
smp = (((ALfloat*)data)[i] * 32767.5f - 0.5f);
smp = min(smp, 32767);
smp = max(smp, -32768);
ALBuf->data[i] = (ALshort)smp;
}
memset(&(ALBuf->data[size]), 0, 16*NewChannels);
ALBuf->format = NewFormat;
+630
View File
@@ -0,0 +1,630 @@
/**
* 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 <stdlib.h>
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#include "alEffect.h"
#include "alThunk.h"
#include "alError.h"
static ALeffect *g_EffectList;
static ALuint g_EffectCount;
static void InitEffectParams(ALeffect *effect, ALenum type);
AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
{
ALCcontext *Context;
ALsizei i;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (n > 0)
{
// Check that enough memory has been allocted in the 'effects' array for n Effects
if (!IsBadWritePtr((void*)effects, n * sizeof(ALuint)))
{
ALeffect **list = &g_EffectList;
while(*list)
list = &(*list)->next;
i = 0;
while(i < n)
{
*list = calloc(1, sizeof(ALeffect));
if(!(*list))
{
// We must have run out or memory
alDeleteEffects(i, effects);
alSetError(AL_OUT_OF_MEMORY);
break;
}
effects[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->effect = effects[i];
InitEffectParams(*list, AL_EFFECT_NULL);
g_EffectCount++;
i++;
list = &(*list)->next;
}
}
}
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects)
{
ALCcontext *Context;
ALeffect *ALEffect;
ALsizei i;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (n >= 0)
{
// Check that all effects are valid
for (i = 0; i < n; i++)
{
if (!alIsEffect(effects[i]))
{
alSetError(AL_INVALID_NAME);
break;
}
}
if (i == n)
{
// All effects are valid
for (i = 0; i < n; i++)
{
// Recheck that the effect is valid, because there could be duplicated names
if (effects[i] && alIsEffect(effects[i]))
{
ALeffect **list;
ALEffect = ((ALeffect*)ALTHUNK_LOOKUPENTRY(effects[i]));
// Remove Source from list of Sources
list = &g_EffectList;
while(*list && *list != ALEffect)
list = &(*list)->next;
if(*list)
*list = (*list)->next;
ALTHUNK_REMOVEENTRY(ALEffect->effect);
memset(ALEffect, 0, sizeof(ALeffect));
free(ALEffect);
g_EffectCount--;
}
}
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
}
AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
{
ALCcontext *Context;
ALeffect **list;
Context = alcGetCurrentContext();
SuspendContext(Context);
list = &g_EffectList;
while(*list && (*list)->effect != effect)
list = &(*list)->next;
ProcessContext(Context);
return ((*list || !effect) ? AL_TRUE : AL_FALSE);
}
AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (effect && alIsEffect(effect))
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
if(param == AL_EFFECT_TYPE)
{
if(iValue == AL_EFFECT_NULL ||
iValue == AL_EFFECT_REVERB)
InitEffectParams(ALEffect, iValue);
else
alSetError(AL_INVALID_VALUE);
}
else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
case AL_REVERB_DECAY_HFLIMIT:
if(iValue == AL_TRUE || iValue == AL_FALSE)
ALEffect->Reverb.DecayHFLimit = iValue;
else
alSetError(AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (effect && alIsEffect(effect))
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
if(param == AL_EFFECT_TYPE)
{
alEffecti(effect, param, piValues[0]);
}
else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
case AL_REVERB_DECAY_HFLIMIT:
alEffecti(effect, param, piValues[0]);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (effect && alIsEffect(effect))
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
case AL_REVERB_DENSITY:
if(flValue >= 0.0f && flValue <= 1.0f)
ALEffect->Reverb.Density = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_DIFFUSION:
if(flValue >= 0.0f && flValue <= 1.0f)
ALEffect->Reverb.Diffusion = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_GAIN:
if(flValue >= 0.0f && flValue <= 1.0f)
ALEffect->Reverb.Gain = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_GAINHF:
if(flValue >= 0.0f && flValue <= 1.0f)
ALEffect->Reverb.GainHF = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_DECAY_TIME:
if(flValue >= 0.1f && flValue <= 20.0f)
ALEffect->Reverb.DecayTime = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_DECAY_HFRATIO:
if(flValue >= 0.1f && flValue <= 2.0f)
ALEffect->Reverb.DecayHFRatio = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_REFLECTIONS_GAIN:
if(flValue >= 0.0f && flValue <= 3.16f)
ALEffect->Reverb.ReflectionsGain = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_REFLECTIONS_DELAY:
if(flValue >= 0.0f && flValue <= 0.3f)
ALEffect->Reverb.ReflectionsDelay = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_LATE_REVERB_GAIN:
if(flValue >= 0.0f && flValue <= 10.0f)
ALEffect->Reverb.LateReverbGain = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_LATE_REVERB_DELAY:
if(flValue >= 0.0f && flValue <= 0.1f)
ALEffect->Reverb.LateReverbDelay = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_AIR_ABSORPTION_GAINHF:
if(flValue >= 0.892f && flValue <= 1.0f)
ALEffect->Reverb.AirAbsorptionGainHF = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REVERB_ROOM_ROLLOFF_FACTOR:
if(flValue >= 0.0f && flValue <= 10.0f)
ALEffect->Reverb.RoomRolloffFactor = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (effect && alIsEffect(effect))
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
case AL_REVERB_DENSITY:
case AL_REVERB_DIFFUSION:
case AL_REVERB_GAIN:
case AL_REVERB_GAINHF:
case AL_REVERB_DECAY_TIME:
case AL_REVERB_DECAY_HFRATIO:
case AL_REVERB_REFLECTIONS_GAIN:
case AL_REVERB_REFLECTIONS_DELAY:
case AL_REVERB_LATE_REVERB_GAIN:
case AL_REVERB_LATE_REVERB_DELAY:
case AL_REVERB_AIR_ABSORPTION_GAINHF:
case AL_REVERB_ROOM_ROLLOFF_FACTOR:
alEffectf(effect, param, pflValues[0]);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (effect && alIsEffect(effect))
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
if(param == AL_EFFECT_TYPE)
{
*piValue = ALEffect->type;
}
else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
case AL_REVERB_DECAY_HFLIMIT:
*piValue = ALEffect->Reverb.DecayHFLimit;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (effect && alIsEffect(effect))
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
if(param == AL_EFFECT_TYPE)
{
alGetEffecti(effect, param, piValues);
}
else if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
case AL_REVERB_DECAY_HFLIMIT:
alGetEffecti(effect, param, piValues);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (effect && alIsEffect(effect))
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
case AL_REVERB_DENSITY:
*pflValue = ALEffect->Reverb.Density;
break;
case AL_REVERB_DIFFUSION:
*pflValue = ALEffect->Reverb.Diffusion;
break;
case AL_REVERB_GAIN:
*pflValue = ALEffect->Reverb.Gain;
break;
case AL_REVERB_GAINHF:
*pflValue = ALEffect->Reverb.GainHF;
break;
case AL_REVERB_DECAY_TIME:
*pflValue = ALEffect->Reverb.DecayTime;
break;
case AL_REVERB_DECAY_HFRATIO:
*pflValue = ALEffect->Reverb.DecayHFRatio;
break;
case AL_REVERB_REFLECTIONS_GAIN:
*pflValue = ALEffect->Reverb.ReflectionsGain;
break;
case AL_REVERB_REFLECTIONS_DELAY:
*pflValue = ALEffect->Reverb.ReflectionsDelay;
break;
case AL_REVERB_LATE_REVERB_GAIN:
*pflValue = ALEffect->Reverb.LateReverbGain;
break;
case AL_REVERB_LATE_REVERB_DELAY:
*pflValue = ALEffect->Reverb.LateReverbDelay;
break;
case AL_REVERB_AIR_ABSORPTION_GAINHF:
*pflValue = ALEffect->Reverb.AirAbsorptionGainHF;
break;
case AL_REVERB_ROOM_ROLLOFF_FACTOR:
*pflValue = ALEffect->Reverb.RoomRolloffFactor;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (effect && alIsEffect(effect))
{
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
if(ALEffect->type == AL_EFFECT_REVERB)
{
switch(param)
{
case AL_REVERB_DENSITY:
case AL_REVERB_DIFFUSION:
case AL_REVERB_GAIN:
case AL_REVERB_GAINHF:
case AL_REVERB_DECAY_TIME:
case AL_REVERB_DECAY_HFRATIO:
case AL_REVERB_REFLECTIONS_GAIN:
case AL_REVERB_REFLECTIONS_DELAY:
case AL_REVERB_LATE_REVERB_GAIN:
case AL_REVERB_LATE_REVERB_DELAY:
case AL_REVERB_AIR_ABSORPTION_GAINHF:
case AL_REVERB_ROOM_ROLLOFF_FACTOR:
alGetEffectf(effect, param, pflValues);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_ENUM);
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
ALvoid ReleaseALEffects(ALvoid)
{
#ifdef _DEBUG
if(g_EffectCount > 0)
AL_PRINT("exit() %d Effect(s) NOT deleted\n", g_EffectCount);
#endif
while(g_EffectList)
{
ALeffect *temp = g_EffectList;
g_EffectList = g_EffectList->next;
// Release effect structure
memset(temp, 0, sizeof(ALeffect));
free(temp);
}
g_EffectCount = 0;
}
static void InitEffectParams(ALeffect *effect, ALenum type)
{
effect->type = type;
switch(type)
{
case AL_EFFECT_REVERB:
effect->Reverb.Density = 1.0f;
effect->Reverb.Diffusion = 1.0f;
effect->Reverb.Gain = 0.32f;
effect->Reverb.GainHF = 0.89f;
effect->Reverb.DecayTime = 1.49f;
effect->Reverb.DecayHFRatio = 0.83f;
effect->Reverb.ReflectionsGain = 0.05f;
effect->Reverb.ReflectionsDelay = 0.007f;
effect->Reverb.LateReverbGain = 1.26f;
effect->Reverb.LateReverbDelay = 0.011f;
effect->Reverb.AirAbsorptionGainHF = 0.994f;
effect->Reverb.RoomRolloffFactor = 0.0f;
effect->Reverb.DecayHFLimit = AL_TRUE;
break;
}
}
+2
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include "alMain.h"
#include "AL/alc.h"
#include "alError.h"
+116 -18
View File
@@ -18,12 +18,18 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "alExtension.h"
#include "alError.h"
#include "alMain.h"
#include "alFilter.h"
#include "alEffect.h"
#include "alAuxEffectSlot.h"
#include "alSource.h"
#include "AL/al.h"
#include "AL/alc.h"
@@ -101,6 +107,43 @@ static ALfunction function[]= {
{ "alDopplerVelocity", (ALvoid *) alDopplerVelocity },
{ "alSpeedOfSound", (ALvoid *) alSpeedOfSound },
{ "alDistanceModel", (ALvoid *) alDistanceModel },
{ "alGenFilters", (ALvoid *) alGenFilters },
{ "alDeleteFilters", (ALvoid *) alDeleteFilters },
{ "alIsFilter", (ALvoid *) alIsFilter },
{ "alFilteri", (ALvoid *) alFilteri },
{ "alFilteriv", (ALvoid *) alFilteriv },
{ "alFilterf", (ALvoid *) alFilterf },
{ "alFilterfv", (ALvoid *) alFilterfv },
{ "alGetFilteri", (ALvoid *) alGetFilteri },
{ "alGetFilteriv", (ALvoid *) alGetFilteriv },
{ "alGetFilterf", (ALvoid *) alGetFilterf },
{ "alGetFilterfv", (ALvoid *) alGetFilterfv },
{ "alGenEffects", (ALvoid *) alGenEffects },
{ "alDeleteEffects", (ALvoid *) alDeleteEffects },
{ "alIsEffect", (ALvoid *) alIsEffect },
{ "alEffecti", (ALvoid *) alEffecti },
{ "alEffectiv", (ALvoid *) alEffectiv },
{ "alEffectf", (ALvoid *) alEffectf },
{ "alEffectfv", (ALvoid *) alEffectfv },
{ "alGetEffecti", (ALvoid *) alGetEffecti },
{ "alGetEffectiv", (ALvoid *) alGetEffectiv },
{ "alGetEffectf", (ALvoid *) alGetEffectf },
{ "alGetEffectfv", (ALvoid *) alGetEffectfv },
{ "alGenAuxiliaryEffectSlots", (ALvoid *) alGenAuxiliaryEffectSlots },
{ "alDeleteAuxiliaryEffectSlots",(ALvoid *) alDeleteAuxiliaryEffectSlots},
{ "alIsAuxiliaryEffectSlot", (ALvoid *) alIsAuxiliaryEffectSlot },
{ "alAuxiliaryEffectSloti", (ALvoid *) alAuxiliaryEffectSloti },
{ "alAuxiliaryEffectSlotiv", (ALvoid *) alAuxiliaryEffectSlotiv },
{ "alAuxiliaryEffectSlotf", (ALvoid *) alAuxiliaryEffectSlotf },
{ "alAuxiliaryEffectSlotfv", (ALvoid *) alAuxiliaryEffectSlotfv },
{ "alGetAuxiliaryEffectSloti", (ALvoid *) alGetAuxiliaryEffectSloti },
{ "alGetAuxiliaryEffectSlotiv", (ALvoid *) alGetAuxiliaryEffectSlotiv},
{ "alGetAuxiliaryEffectSlotf", (ALvoid *) alGetAuxiliaryEffectSlotf },
{ "alGetAuxiliaryEffectSlotfv", (ALvoid *) alGetAuxiliaryEffectSlotfv},
{ NULL, (ALvoid *) NULL } };
static ALenums enumeration[]={
@@ -135,6 +178,18 @@ static ALenums enumeration[]={
{ (ALchar *)"AL_STATIC", AL_STATIC },
{ (ALchar *)"AL_STREAMING", AL_STREAMING },
{ (ALchar *)"AL_UNDETERMINED", AL_UNDETERMINED },
{ (ALchar *)"AL_METERS_PER_UNIT", AL_METERS_PER_UNIT },
// Source EFX Properties
{ (ALchar *)"AL_DIRECT_FILTER", AL_DIRECT_FILTER },
{ (ALchar *)"AL_AUXILIARY_SEND_FILTER", AL_AUXILIARY_SEND_FILTER },
{ (ALchar *)"AL_AIR_ABSORPTION_FACTOR", AL_AIR_ABSORPTION_FACTOR },
{ (ALchar *)"AL_ROOM_ROLLOFF_FACTOR", AL_ROOM_ROLLOFF_FACTOR },
{ (ALchar *)"AL_CONE_OUTER_GAINHF", AL_CONE_OUTER_GAINHF },
{ (ALchar *)"AL_DIRECT_FILTER_GAINHF_AUTO", AL_DIRECT_FILTER_GAINHF_AUTO },
{ (ALchar *)"AL_AUXILIARY_SEND_FILTER_GAIN_AUTO", AL_AUXILIARY_SEND_FILTER_GAIN_AUTO },
{ (ALchar *)"AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO", AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO},
// Source State information
{ (ALchar *)"AL_SOURCE_STATE", AL_SOURCE_STATE },
@@ -156,6 +211,8 @@ static ALenums enumeration[]={
{ (ALchar *)"AL_FORMAT_STEREO_FLOAT32", AL_FORMAT_STEREO_FLOAT32 },
{ (ALchar *)"AL_FORMAT_MONO_IMA4", AL_FORMAT_MONO_IMA4 },
{ (ALchar *)"AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 },
{ (ALchar *)"AL_FORMAT_QUAD8_LOKI", AL_FORMAT_QUAD8_LOKI },
{ (ALchar *)"AL_FORMAT_QUAD16_LOKI", AL_FORMAT_QUAD16_LOKI },
{ (ALchar *)"AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 },
{ (ALchar *)"AL_FORMAT_QUAD16", AL_FORMAT_QUAD16 },
{ (ALchar *)"AL_FORMAT_QUAD32", AL_FORMAT_QUAD32 },
@@ -211,8 +268,52 @@ static ALenums enumeration[]={
{ (ALchar *)"AL_EXPONENT_DISTANCE", AL_EXPONENT_DISTANCE },
{ (ALchar *)"AL_EXPONENT_DISTANCE_CLAMPED", AL_EXPONENT_DISTANCE_CLAMPED },
// Filter types
{ (ALchar *)"AL_FILTER_TYPE", AL_FILTER_TYPE },
{ (ALchar *)"AL_FILTER_NULL", AL_FILTER_NULL },
{ (ALchar *)"AL_FILTER_LOWPASS", AL_FILTER_LOWPASS },
{ (ALchar *)"AL_FILTER_HIGHPASS", AL_FILTER_HIGHPASS },
{ (ALchar *)"AL_FILTER_BANDPASS", AL_FILTER_BANDPASS },
// Filter params
{ (ALchar *)"AL_LOWPASS_GAIN", AL_LOWPASS_GAIN },
{ (ALchar *)"AL_LOWPASS_GAINHF", AL_LOWPASS_GAINHF },
// Effect types
{ (ALchar *)"AL_EFFECT_TYPE", AL_EFFECT_TYPE },
{ (ALchar *)"AL_EFFECT_NULL", AL_EFFECT_NULL },
{ (ALchar *)"AL_EFFECT_REVERB", AL_EFFECT_REVERB },
{ (ALchar *)"AL_EFFECT_CHORUS", AL_EFFECT_CHORUS },
{ (ALchar *)"AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION },
{ (ALchar *)"AL_EFFECT_ECHO", AL_EFFECT_ECHO },
{ (ALchar *)"AL_EFFECT_FLANGER", AL_EFFECT_FLANGER },
{ (ALchar *)"AL_EFFECT_FREQUENCY_SHIFTER", AL_EFFECT_FREQUENCY_SHIFTER },
{ (ALchar *)"AL_EFFECT_VOCAL_MORPHER", AL_EFFECT_VOCAL_MORPHER },
{ (ALchar *)"AL_EFFECT_PITCH_SHIFTER", AL_EFFECT_PITCH_SHIFTER },
{ (ALchar *)"AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR },
{ (ALchar *)"AL_EFFECT_AUTOWAH", AL_EFFECT_AUTOWAH },
{ (ALchar *)"AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR },
{ (ALchar *)"AL_EFFECT_EQUALIZER", AL_EFFECT_EQUALIZER },
// Reverb params
{ (ALchar *)"AL_REVERB_DENSITY", AL_REVERB_DENSITY },
{ (ALchar *)"AL_REVERB_DIFFUSION", AL_REVERB_DIFFUSION },
{ (ALchar *)"AL_REVERB_GAIN", AL_REVERB_GAIN },
{ (ALchar *)"AL_REVERB_GAINHF", AL_REVERB_GAINHF },
{ (ALchar *)"AL_REVERB_DECAY_TIME", AL_REVERB_DECAY_TIME },
{ (ALchar *)"AL_REVERB_DECAY_HFRATIO", AL_REVERB_DECAY_HFRATIO },
{ (ALchar *)"AL_REVERB_REFLECTIONS_GAIN", AL_REVERB_REFLECTIONS_GAIN },
{ (ALchar *)"AL_REVERB_REFLECTIONS_DELAY", AL_REVERB_REFLECTIONS_DELAY },
{ (ALchar *)"AL_REVERB_LATE_REVERB_GAIN", AL_REVERB_LATE_REVERB_GAIN },
{ (ALchar *)"AL_REVERB_LATE_REVERB_DELAY", AL_REVERB_LATE_REVERB_DELAY },
{ (ALchar *)"AL_REVERB_AIR_ABSORPTION_GAINHF", AL_REVERB_AIR_ABSORPTION_GAINHF },
{ (ALchar *)"AL_REVERB_ROOM_ROLLOFF_FACTOR", AL_REVERB_ROOM_ROLLOFF_FACTOR },
{ (ALchar *)"AL_REVERB_DECAY_HFLIMIT", AL_REVERB_DECAY_HFLIMIT },
// Default
{ (ALchar *)NULL, (ALenum ) 0 } };
{ (ALchar *)NULL, (ALenum)0 }
};
@@ -220,7 +321,8 @@ ALAPI ALboolean ALAPIENTRY alIsExtensionPresent(const ALchar *extName)
{
ALboolean bIsSupported = AL_FALSE;
ALCcontext *pContext;
char *ptr, *ext;
const char *ptr;
size_t len;
if (!extName)
{
@@ -235,32 +337,28 @@ ALAPI ALboolean ALAPIENTRY alIsExtensionPresent(const ALchar *extName)
return AL_FALSE;
}
ext = strdup(extName);
ptr = ext;
do {
*ptr = (char)toupper(*ptr);
} while(*(ptr++));
SuspendContext(pContext);
len = strlen(extName);
ptr = pContext->ExtensionList;
while((ptr=strstr(ptr, ext)) != NULL)
while(ptr && *ptr)
{
if(ptr == pContext->ExtensionList || ptr[-1] == ' ')
if(strncasecmp(ptr, extName, len) == 0 &&
(ptr[len] == '\0' || isspace(ptr[len])))
{
char e = ptr[strlen(ext)];
if(e == ' ' || e == 0)
{
bIsSupported = AL_TRUE;
break;
}
bIsSupported = AL_TRUE;
break;
}
if((ptr=strchr(ptr, ' ')) != NULL)
{
do {
++ptr;
} while(isspace(*ptr));
}
ptr++;
}
ProcessContext(pContext);
free(ext);
return bIsSupported;
}
+424
View File
@@ -0,0 +1,424 @@
/**
* 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 <stdlib.h>
#include "AL/al.h"
#include "AL/alc.h"
#include "alMain.h"
#include "alFilter.h"
#include "alThunk.h"
#include "alError.h"
static ALfilter *g_FilterList;
static ALuint g_FilterCount;
static void InitFilterParams(ALfilter *filter, ALenum type);
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
{
ALCcontext *Context;
ALsizei i;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (n > 0)
{
// Check that enough memory has been allocted in the 'filters' array for n Filters
if (!IsBadWritePtr((void*)filters, n * sizeof(ALuint)))
{
ALfilter **list = &g_FilterList;
while(*list)
list = &(*list)->next;
i = 0;
while(i < n)
{
*list = calloc(1, sizeof(ALfilter));
if(!(*list))
{
// We must have run out or memory
alDeleteFilters(i, filters);
alSetError(AL_OUT_OF_MEMORY);
break;
}
filters[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->filter = filters[i];
InitFilterParams(*list, AL_FILTER_NULL);
g_FilterCount++;
i++;
list = &(*list)->next;
}
}
}
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters)
{
ALCcontext *Context;
ALfilter *ALFilter;
ALsizei i;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (n >= 0)
{
// Check that all filters are valid
for (i = 0; i < n; i++)
{
if (!alIsFilter(filters[i]))
{
alSetError(AL_INVALID_NAME);
break;
}
}
if (i == n)
{
// All filters are valid
for (i = 0; i < n; i++)
{
// Recheck that the filter is valid, because there could be duplicated names
if (filters[i] && alIsFilter(filters[i]))
{
ALfilter **list;
ALFilter = ((ALfilter*)ALTHUNK_LOOKUPENTRY(filters[i]));
// Remove Source from list of Sources
list = &g_FilterList;
while(*list && *list != ALFilter)
list = &(*list)->next;
if(*list)
*list = (*list)->next;
ALTHUNK_REMOVEENTRY(ALFilter->filter);
memset(ALFilter, 0, sizeof(ALfilter));
free(ALFilter);
g_FilterCount--;
}
}
}
}
else
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
}
AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
{
ALCcontext *Context;
ALfilter **list;
Context = alcGetCurrentContext();
SuspendContext(Context);
list = &g_FilterList;
while(*list && (*list)->filter != filter)
list = &(*list)->next;
ProcessContext(Context);
return ((*list || !filter) ? AL_TRUE : AL_FALSE);
}
AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
{
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
switch(param)
{
case AL_FILTER_TYPE:
if(iValue == AL_FILTER_NULL ||
iValue == AL_FILTER_LOWPASS)
InitFilterParams(ALFilter, iValue);
else
alSetError(AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
{
switch(param)
{
case AL_FILTER_TYPE:
alFilteri(filter, param, piValues[0]);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
{
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
switch(param)
{
case AL_LOWPASS_GAIN:
if(ALFilter->type == AL_FILTER_LOWPASS)
{
if(flValue >= 0.0f && flValue <= 1.0f)
ALFilter->Gain = flValue;
}
else
alSetError(AL_INVALID_ENUM);
break;
case AL_LOWPASS_GAINHF:
if(ALFilter->type == AL_FILTER_LOWPASS)
{
if(flValue >= 0.0f && flValue <= 1.0f)
ALFilter->GainHF = flValue;
}
else
alSetError(AL_INVALID_ENUM);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
{
switch(param)
{
case AL_LOWPASS_GAIN:
case AL_LOWPASS_GAINHF:
alFilterf(filter, param, pflValues[0]);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue)
{
ALCcontext *Context;
(void)piValue;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
{
switch(param)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues)
{
ALCcontext *Context;
(void)piValues;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
{
switch(param)
{
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
{
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(filter);
switch(param)
{
case AL_LOWPASS_GAIN:
if(ALFilter->type == AL_FILTER_LOWPASS)
*pflValue = ALFilter->Gain;
else
alSetError(AL_INVALID_ENUM);
break;
case AL_LOWPASS_GAINHF:
if(ALFilter->type == AL_FILTER_LOWPASS)
*pflValue = ALFilter->GainHF;
else
alSetError(AL_INVALID_ENUM);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues)
{
ALCcontext *Context;
Context = alcGetCurrentContext();
SuspendContext(Context);
if (filter && alIsFilter(filter))
{
switch(param)
{
case AL_LOWPASS_GAIN:
case AL_LOWPASS_GAINHF:
alGetFilterf(filter, param, pflValues);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
}
else
alSetError(AL_INVALID_NAME);
ProcessContext(Context);
}
ALvoid ReleaseALFilters(ALvoid)
{
#ifdef _DEBUG
if(g_FilterCount > 0)
AL_PRINT("exit() %d Filter(s) NOT deleted\n", g_FilterCount);
#endif
while(g_FilterList)
{
ALfilter *temp = g_FilterList;
g_FilterList = g_FilterList->next;
// Release filter structure
memset(temp, 0, sizeof(ALfilter));
free(temp);
}
g_FilterCount = 0;
}
static void InitFilterParams(ALfilter *filter, ALenum type)
{
filter->type = type;
filter->Gain = 1.0;
filter->GainHF = 1.0;
}
+24
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include "alMain.h"
#include "AL/alc.h"
#include "alError.h"
@@ -41,6 +43,13 @@ ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
alSetError(AL_INVALID_VALUE);
break;
case AL_METERS_PER_UNIT:
if (flValue > 0.0f)
pContext->Listener.MetersPerUnit = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -112,6 +121,13 @@ ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
alSetError(AL_INVALID_VALUE);
break;
case AL_METERS_PER_UNIT:
if (pflValues[0] > 0.0f)
pContext->Listener.MetersPerUnit = pflValues[0];
else
alSetError(AL_INVALID_VALUE);
break;
case AL_POSITION:
pContext->Listener.Position[0] = pflValues[0];
pContext->Listener.Position[1] = pflValues[1];
@@ -274,6 +290,10 @@ ALAPI ALvoid ALAPIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue)
*pflValue = pContext->Listener.Gain;
break;
case AL_METERS_PER_UNIT:
*pflValue = pContext->Listener.MetersPerUnit;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -350,6 +370,10 @@ ALAPI ALvoid ALAPIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues)
pflValues[0] = pContext->Listener.Gain;
break;
case AL_METERS_PER_UNIT:
pflValues[0] = pContext->Listener.MetersPerUnit;
break;
case AL_POSITION:
pflValues[0] = pContext->Listener.Position[0];
pflValues[1] = pContext->Listener.Position[1];
+184 -14
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include <math.h>
#include <float.h>
@@ -28,6 +30,7 @@
#include "alSource.h"
#include "alBuffer.h"
#include "alThunk.h"
#include "alAuxEffectSlot.h"
static ALvoid InitSourceParams(ALsource *pSource);
static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset);
@@ -65,22 +68,22 @@ ALAPI ALvoid ALAPIENTRY alGenSources(ALsizei n,ALuint *sources)
while(i < n)
{
*list = calloc(1, sizeof(ALsource));
if(*list)
if(!(*list))
{
sources[i]=(ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->source = sources[i];
InitSourceParams(*list);
Context->SourceCount++;
i++;
list = &(*list)->next;
alDeleteSources(i, sources);
alSetError(AL_OUT_OF_MEMORY);
break;
}
}
// If we didn't create all the Sources, we must have run out or memory
if(i != n)
alSetError(AL_OUT_OF_MEMORY);
sources[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->source = sources[i];
InitSourceParams(*list);
Context->SourceCount++;
i++;
list = &(*list)->next;
}
}
else
{
@@ -119,7 +122,7 @@ ALAPI ALvoid ALAPIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
ALCdevice *Device;
ALsource *ALSource;
ALsource **list;
ALsizei i;
ALsizei i, j;
ALbufferlistitem *ALBufferList;
ALboolean bSourcesValid = AL_TRUE;
@@ -171,6 +174,13 @@ ALAPI ALvoid ALAPIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
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--;
@@ -343,6 +353,27 @@ ALAPI ALvoid ALAPIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
alSetError(AL_INVALID_VALUE);
break;
case AL_CONE_OUTER_GAINHF:
if ((flValue >= 0.0f) && (flValue <= 1.0f))
pSource->OuterGainHF = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_AIR_ABSORPTION_FACTOR:
if (flValue >= 0.0f && flValue <= 10.0f)
pSource->AirAbsorptionFactor = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_ROOM_ROLLOFF_FACTOR:
if (flValue >= 0.0f && flValue <= 1.0f)
pSource->RoomRolloffFactor = flValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
@@ -463,9 +494,12 @@ ALAPI ALvoid ALAPIENTRY alSourcefv(ALuint source, ALenum eParam, const ALfloat *
case AL_MIN_GAIN:
case AL_MAX_GAIN:
case AL_CONE_OUTER_GAIN:
case AL_CONE_OUTER_GAINHF:
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
case AL_AIR_ABSORPTION_FACTOR:
case AL_ROOM_ROLLOFF_FACTOR:
alSourcef(source, eParam, pflValues[0]);
break;
@@ -638,6 +672,43 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
alSetError(AL_INVALID_VALUE);
break;
case AL_DIRECT_FILTER:
if(alIsFilter(lValue))
{
ALfilter *filter = (ALfilter*)ALTHUNK_LOOKUPENTRY(lValue);
if(!filter)
{
pSource->DirectFilter.type = AL_FILTER_NULL;
pSource->DirectFilter.filter = 0;
}
else
memcpy(&pSource->DirectFilter, filter, sizeof(*filter));
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_DIRECT_FILTER_GAINHF_AUTO:
if(lValue == AL_TRUE || lValue == AL_FALSE)
pSource->DryGainHFAuto = lValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
if(lValue == AL_TRUE || lValue == AL_FALSE)
pSource->WetGainAuto = lValue;
else
alSetError(AL_INVALID_VALUE);
break;
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
if(lValue == AL_TRUE || lValue == AL_FALSE)
pSource->WetGainHFAuto = lValue;
else
alSetError(AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -666,6 +737,8 @@ ALAPI void ALAPIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, AL
if (alIsSource(source))
{
ALsource *pSource = ((ALsource *)ALTHUNK_LOOKUPENTRY(source));
switch (eParam)
{
case AL_POSITION:
@@ -674,6 +747,35 @@ ALAPI void ALAPIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, AL
alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3);
break;
case AL_AUXILIARY_SEND_FILTER:
if(lValue2 >= 0 && lValue2 < MAX_SENDS &&
(alIsAuxiliaryEffectSlot(lValue1) || lValue1 == 0) &&
alIsFilter(lValue3))
{
ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(lValue1);
ALfilter *ALFilter = (ALfilter*)ALTHUNK_LOOKUPENTRY(lValue3);
/* Release refcount on the previous slot, and add one for
* the new slot */
if(pSource->Send[lValue2].Slot)
pSource->Send[lValue2].Slot->refcount--;
pSource->Send[lValue2].Slot = ALEffectSlot;
if(pSource->Send[lValue2].Slot)
pSource->Send[lValue2].Slot->refcount++;
if(!ALFilter)
{
/* Disable filter */
pSource->Send[lValue2].WetFilter.type = 0;
pSource->Send[lValue2].WetFilter.filter = 0;
}
else
memcpy(&pSource->Send[lValue2].WetFilter, ALFilter, sizeof(*ALFilter));
}
else
alSetError(AL_INVALID_VALUE);
break;
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -718,12 +820,17 @@ ALAPI void ALAPIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plVa
case AL_MAX_DISTANCE:
case AL_ROLLOFF_FACTOR:
case AL_REFERENCE_DISTANCE:
case AL_DIRECT_FILTER:
case AL_DIRECT_FILTER_GAINHF_AUTO:
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
alSourcei(source, eParam, plValues[0]);
break;
case AL_POSITION:
case AL_VELOCITY:
case AL_DIRECTION:
case AL_AUXILIARY_SEND_FILTER:
alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]);
break;
@@ -794,6 +901,10 @@ ALAPI ALvoid ALAPIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflV
*pflValue = pSource->flOuterGain;
break;
case AL_CONE_OUTER_GAINHF:
*pflValue = pSource->OuterGainHF;
break;
case AL_SEC_OFFSET:
case AL_SAMPLE_OFFSET:
case AL_BYTE_OFFSET:
@@ -815,6 +926,14 @@ ALAPI ALvoid ALAPIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflV
*pflValue = pSource->flRefDistance;
break;
case AL_AIR_ABSORPTION_FACTOR:
*pflValue = pSource->AirAbsorptionFactor;
break;
case AL_ROOM_ROLLOFF_FACTOR:
*pflValue = pSource->RoomRolloffFactor;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -922,6 +1041,9 @@ ALAPI ALvoid ALAPIENTRY alGetSourcefv(ALuint source, ALenum eParam, ALfloat *pfl
case AL_CONE_INNER_ANGLE:
case AL_CONE_OUTER_ANGLE:
case AL_REFERENCE_DISTANCE:
case AL_CONE_OUTER_GAINHF:
case AL_AIR_ABSORPTION_FACTOR:
case AL_ROOM_ROLLOFF_FACTOR:
alGetSourcef(source, eParam, pflValues);
break;
@@ -1046,6 +1168,22 @@ ALAPI ALvoid ALAPIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValu
alSetError(AL_INVALID_OPERATION);
break;
case AL_DIRECT_FILTER:
*plValue = pSource->DirectFilter.filter;
break;
case AL_DIRECT_FILTER_GAINHF_AUTO:
*plValue = pSource->DryGainHFAuto;
break;
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
*plValue = pSource->WetGainAuto;
break;
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
*plValue = pSource->WetGainHFAuto;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -1155,6 +1293,10 @@ ALAPI void ALAPIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValue
case AL_ROLLOFF_FACTOR:
case AL_REFERENCE_DISTANCE:
case AL_SOURCE_TYPE:
case AL_DIRECT_FILTER:
case AL_DIRECT_FILTER_GAINHF_AUTO:
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
alGetSourcei(source, eParam, plValues);
break;
@@ -1831,6 +1973,13 @@ static ALvoid InitSourceParams(ALsource *pSource)
pSource->flMinGain = 0.0f;
pSource->flMaxGain = 1.0f;
pSource->flOuterGain = 0.0f;
pSource->OuterGainHF = 1.0f;
pSource->DryGainHFAuto = AL_TRUE;
pSource->WetGainAuto = AL_TRUE;
pSource->WetGainHFAuto = AL_TRUE;
pSource->AirAbsorptionFactor = 0.0f;
pSource->RoomRolloffFactor = 0.0f;
pSource->state = AL_INITIAL;
pSource->lSourceType = AL_UNDETERMINED;
@@ -2133,3 +2282,24 @@ static ALint GetByteOffset(ALsource *pSource)
return lByteOffset;
}
ALvoid ReleaseALSources(ALCcontext *Context)
{
#ifdef _DEBUG
if(Context->SourceCount > 0)
AL_PRINT("alcDestroyContext(): %d Source(s) NOT deleted\n", Context->SourceCount);
#endif
while(Context->Source)
{
ALsource *temp = Context->Source;
Context->Source = Context->Source->next;
// Release source structure
ALTHUNK_REMOVEENTRY(temp->source);
memset(temp, 0, sizeof(ALsource));
free(temp);
}
Context->SourceCount = 0;
}
+2
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include "alMain.h"
#include "AL/alc.h"
+2
View File
@@ -18,6 +18,8 @@
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include "alMain.h"
+24 -7
View File
@@ -1,8 +1,9 @@
# OpenAL config file. Options that are not under a block or are under the
# [general] block are for general, non-backend-specific options. Blocks may
# appear multiple times, and duplicated options will take the last value
# specified. The system-wide settings can be put in /etc/openal/config and
# user-specific override settings in ~/.openalrc
# specified.
# The system-wide settings can be put in /etc/openal/alsoft.conf and user-
# specific override settings in ~/.alsoftrc.
# 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
@@ -36,25 +37,35 @@ cf_level = 0 # Sets the crossfeed level for stereo output. Valid values are:
frequency = 44100 # Sets the output frequency. Default is 44100
refresh = 0 # Sets the number of frames-per-update. Default is calculated as
# 8192*frequency/22050. Note that the actual granularity may or
# may not be less than this.
refresh = 8192 # Sets the buffer size, in frames. Default is 8192. Note that
# the actual granularity may or may not be less than this.
sources = 256 # Sets the maximum number of allocatable sources. Lower values
# may help for systems with apps that try to play more sounds
# than the CPU can handle. Default is 256
drivers = # Sets the backend driver list order, comma-seperated. Unknown
# backends and duplicated names are ignored, and unlisted backends
# won't be considered for use. An empty list means the default.
# Default is:
# alsa,oss,dsound,winmm
# alsa,oss,dsound,winmm,wave
[alsa] # ALSA backend stuff
device = default # Sets the device name for the default playback device.
# Default is default
periods = 4 # Sets the number of update buffers. Default is 4
periods = 0 # Sets the number of update buffers for playback. A value of 0
# means auto-select. Default is 0
capture = default # Sets the device name for the default capture device.
# Default is default
mmap = true # Sets whether to try using mmap mode (helps reduce latencies and
# CPU consumption). If mmap isn't available, it will automatically
# fall back to non-mmap mode. True, yes, on, and non-0 values will
# attempt to use mmap. 0 and anything else will force mmap off.
# Default is true.
[oss] # OSS backend stuff
device = /dev/dsp # Sets the device name for OSS output. Default is /dev/dsp
@@ -67,3 +78,9 @@ capture = /dev/dsp # Sets the device name for OSS capture. Default is /dev/dsp
[winmm] # Windows Multimedia backend stuff
# Nothing yet...
[wave] # Wave File Writer stuff
file = # Sets the filename of the wave file to write to. An empty name
# prevents the backend from opening, even when explicitly requested.
# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION!
# Default is empty
+3
View File
@@ -19,6 +19,9 @@
/* Define if we have the sqrtf function */
#cmakedefine HAVE_SQRTF
/* Define if we have the acosf function */
#cmakedefine HAVE_ACOSF
/* Define if we have the strtof function */
#cmakedefine HAVE_STRTOF