Compare commits

..

131 Commits

Author SHA1 Message Date
Chris Robinson 3ad86a1c1b Release 1.11.753 2010-01-17 17:46:27 -08:00
Chris Robinson 931f5875cd Fix speaker angle fixup 2010-01-12 09:11:46 -08:00
Chris Robinson f22b02a762 al_print doesn't need to be inline 2010-01-12 09:05:57 -08:00
Chris Robinson 505f61ff43 Properly trace the invalid speaker angle 2010-01-12 08:50:32 -08:00
Chris Robinson 0c2efa1253 Use GCC's format attribute for al_printf 2010-01-12 08:48:25 -08:00
Chris Robinson 5921e18be2 Fix some typos with the solaris backend 2010-01-12 08:28:07 -08:00
Chris Robinson 5b9e6fe440 Only allow 8- and 16-bit, and mono and stereo, wave file output 2010-01-12 08:26:25 -08:00
Chris Robinson 35ba7d70dc Consolidate some source offset handling code 2010-01-12 02:43:37 -08:00
Chris Robinson 026b4b8f4c Better handle large second offsets 2010-01-12 02:26:38 -08:00
Chris Robinson c924a50bed Don't use a flag to set an error when applying the source offset 2010-01-12 02:22:38 -08:00
Chris Robinson 574792d2e1 Fix Windows compilation 2010-01-11 23:47:03 -08:00
Chris Robinson ab2eb5a603 Check buffer size when copying padding instead of the data pointer 2010-01-11 10:58:33 -08:00
Chris Robinson 3d7f925d52 Add helpful values to the resampler enum 2010-01-11 07:02:29 -08:00
Chris Robinson 93b584ff84 Add a cosine resampler 2010-01-11 06:19:54 -08:00
Chris Robinson 705849ca73 Add an option for point resampling 2010-01-11 05:37:20 -08:00
Chris Robinson 1a57f095e8 Hold global lock during mixing only when iterating device contexts 2010-01-11 03:57:49 -08:00
Chris Robinson ac9c2e8c4a Cleanup OSS/Solaris loop a bit 2010-01-10 12:40:59 -08:00
Chris Robinson 45f8efec41 Return the default config string for empty entries 2010-01-09 06:48:43 -08:00
Chris Robinson ef7df2416d Hide OSS and Solaris devices if their files can't be stat'd 2010-01-09 06:40:50 -08:00
Chris Robinson cb113315f7 Promote AL_EXT_source_distance_model to complete 2010-01-09 03:27:16 -08:00
Chris Robinson d61f90a9c2 Make sure the device handle is valid when getting the device error 2010-01-09 03:25:13 -08:00
Chris Robinson 3d11fb219e Hold the default context extensions globally 2010-01-09 02:48:18 -08:00
Chris Robinson 4d9a368f96 Suppress connection refused errors
Since that just typically means the server isn't running
2010-01-08 01:43:27 -08:00
Chris Robinson 43220b604c Reduce some indentation 2010-01-08 01:21:57 -08:00
Chris Robinson 91f28fa87c Try the PulseAudio backend first 2010-01-08 01:08:27 -08:00
Chris Robinson 82547db2db Prepare the pcm handle after recovering 2010-01-06 23:02:28 -08:00
Chris Robinson 64ac3a4739 Use snd_pcm_recover in more places 2010-01-06 22:55:20 -08:00
Chris Robinson c90616b963 Use snd_pcm_recover to recover from certain device errors 2010-01-06 22:50:30 -08:00
Chris Robinson 0ceaa01c3d Adjust PulseAudio's capture latency 2009-12-30 15:33:16 -08:00
Chris Robinson 7d7e503603 Properly retrieve device-inspecific errors 2009-12-28 23:29:49 -08:00
Chris Robinson 7ee81eac0f Store ALC errors with the device when possible 2009-12-28 23:19:13 -08:00
Chris Robinson c9a08fc7b2 Remove some unneeded functions 2009-12-28 13:12:45 -08:00
Chris Robinson 69ab93a824 Add a function to check if a config option is set to a non-empty value 2009-12-28 13:08:15 -08:00
Chris Robinson 179b660eee Enforce a lower bound playback frequency of 8khz 2009-12-28 12:47:59 -08:00
Chris Robinson a0ef7be9a5 Improve layout parsing and allow using long names for speakers 2009-12-28 11:49:55 -08:00
Chris Robinson 2a735b14dc Add an option to spawn a PulseAudio server on request 2009-12-28 10:49:31 -08:00
Chris Robinson a294dd8d9b Be more lenient in signaling the mainloop 2009-12-28 10:15:59 -08:00
Chris Robinson dc1522282b Try to find a compatible format from Pulse's default sink 2009-12-27 11:05:59 -08:00
Chris Robinson 528a4c6a02 Update panning for existing AL contexts when creating a new one 2009-12-26 20:27:14 -08:00
Chris Robinson 1770a8b62b A NULL Pulse context won't have a valid error code 2009-12-26 12:18:16 -08:00
Chris Robinson 77a0a6de95 Wait for the buffer attrib update from pulse to finish 2009-12-26 11:30:41 -08:00
Chris Robinson c1fd977e79 Consolidate pulse capture failure path 2009-12-26 10:46:29 -08:00
Chris Robinson cbbda93292 Make sure a proper channel map is set for pulse capture 2009-12-26 09:17:03 -08:00
Chris Robinson c6340ce12d Clean up some loading checks 2009-12-26 08:49:11 -08:00
Chris Robinson 7bc739e965 Use the proper logging function 2009-12-26 08:16:25 -08:00
Chris Robinson 9f988808c7 Start and stop PortAudio's stream in the proper methods 2009-12-26 08:14:28 -08:00
Chris Robinson 6e9ce47a4b GetConfigValueBool should take an int, not a float 2009-12-26 07:42:57 -08:00
Chris Robinson 89f59c0e1c Shorten a long line 2009-12-26 07:42:16 -08:00
Chris Robinson 3793919892 Capture as much as possible directly from PulseAudio 2009-12-25 17:56:57 -08:00
Chris Robinson d1699d50f6 Add missing newline 2009-12-25 15:18:32 -08:00
Chris Robinson b94d950b1e Undefine no longer needed macro 2009-12-25 14:11:43 -08:00
Chris Robinson d3e77a0f63 Fix incorrect error check 2009-12-25 13:19:25 -08:00
Chris Robinson 965a71ee90 Only use pa_stream_set_buffer_attr_callback when available (0.9.15+) 2009-12-25 13:17:21 -08:00
Chris Robinson fd794b44b2 Use pa_stream_begin_write when available for "zero-copy" writing
Must be compiled against 0.9.16 or newer to be available. It will fall back to
the old method if the function is not available at run-time.
2009-12-25 13:11:17 -08:00
Chris Robinson c9dcba17a9 Check error returns instead of error string 2009-12-25 13:05:04 -08:00
Chris Robinson 88de4e15b3 Mark the source for updating when setting a buffer on it
Changing the buffer can change the playback format, which can require different
source parameter calculations. Queueing a buffer on a source that has no
buffers (or only buffers without a format, eg. buffer 0) has the same effect
2009-12-25 05:09:29 -08:00
Chris Robinson 7f0c6629b9 Use a 64-bit value to scale potentially-large numbers 2009-12-24 15:41:45 -08:00
Chris Robinson f6ca39403d Use the Pulse server-specified playback rate by default 2009-12-24 15:35:22 -08:00
Chris Robinson ea7cf35ea4 Use pa_xmalloc instead of pa_xmalloc0 2009-12-24 07:38:46 -08:00
Chris Robinson accea119d9 Update pulse capture ring buffer in 25ms chunks 2009-12-24 04:08:04 -08:00
Chris Robinson 6ea7b43c90 Don't force latency adjustment with PulseAudio 2009-12-23 13:59:58 -08:00
Chris Robinson ddfad996a9 Don't render mono as stereo 2009-12-21 02:59:30 -08:00
Chris Robinson d786f99094 Scale samples down when converting stereo to mono 2009-12-21 02:27:25 -08:00
Chris Robinson 008563450c Improve some indentations 2009-12-20 21:50:00 -08:00
Chris Robinson 69c238a2e6 Properly retrieve the device frequency 2009-12-20 21:19:57 -08:00
Chris Robinson b3fdf170b1 Fix header comment for AL_PITCH 2009-12-16 22:50:54 -08:00
Chris Robinson 56cc038603 Improve initial decay calculations for sends to reverb 2009-12-10 18:37:36 -08:00
Chris Robinson 4c83c689a8 Use the specified reverb air absorption value for wet sends 2009-12-10 18:22:45 -08:00
Chris Robinson 2b7953c472 Track whether a context is suspended or not 2009-12-09 12:14:53 -08:00
Chris Robinson 368ef1cea9 Store the source state locally after making sure it needs mixing 2009-12-09 11:56:53 -08:00
Chris Robinson bd696a6b37 Fix IMA ADPCM offset calculation 2009-12-09 09:50:09 -08:00
Chris Robinson a9fc272e39 Prettify CMake checks for compiler switches 2009-12-09 08:46:35 -08:00
Chris Robinson c5952d1ddc Move the pkg-config file to the base directory 2009-12-09 07:36:06 -08:00
Chris Robinson 656a406377 Use an inline function to calculate the low-pass filter coefficient 2009-12-09 07:21:59 -08:00
Chris Robinson 5fcd6cc510 Split non-attenuated source calculations into a separate function 2009-12-09 07:02:26 -08:00
Chris Robinson e09b6020a6 Fix typo for reverb creation 2009-12-09 06:46:06 -08:00
Chris Robinson 84d2d623b6 Add a head-dampening option
This simulates occlusion of the player's head for sounds coming from behind,
when outputing to mono or stereo
2009-12-08 14:18:07 -08:00
Chris Robinson 1694e5bd12 Store the original pre-clamped distance instead of re-computing it 2009-12-08 10:12:18 -08:00
Chris Robinson 5170e251f9 Use the correct wet filter history offset 2009-12-07 12:45:23 -08:00
Chris Robinson 4697e946d3 Internally store 32-bit float buffer data, and mix accordingly 2009-12-07 10:35:30 -08:00
Chris Robinson 9286e3984c Move default channel order setting out of the header 2009-12-07 04:19:33 -08:00
Chris Robinson 88f3d747b7 Add a simple README 2009-12-07 01:05:01 -08:00
Chris Robinson d4427c54ea Change internal order to match WFX 2009-12-07 00:51:27 -08:00
Chris Robinson 92ade80557 Fix 6.1 channel order 2009-12-07 00:49:56 -08:00
Chris Robinson 8138446b8c Restrict setting some wet path values to active sends only 2009-12-06 03:59:12 -08:00
Chris Robinson 58ecc7fad4 Check for potential NULL accesses with the IsBadWritePtr wrapper 2009-12-04 01:33:50 -08:00
Chris Robinson 311cc5c62f Don't wait to accept stream connections 2009-12-03 04:43:38 -08:00
Chris Robinson 4a928ea9fa Don't signal on synchronous changes and don't wait to accept context changes 2009-12-02 08:10:45 -08:00
Chris Robinson c1eb444a39 Remove some assumptions of 16-bit internal storage 2009-12-02 05:55:33 -08:00
Chris Robinson b5270e0bb3 Use a channel-map to specify the output device channel order 2009-12-02 04:03:51 -08:00
Chris Robinson 6cfc31777b Add an option for real-time priority mixing
Default to disable for now, as a safety precaution
2009-12-01 23:15:09 -08:00
Chris Robinson 0e1e8503e0 Properly accept PulseAudio's mainloop signal on connection failure 2009-12-01 22:42:43 -08:00
Chris Robinson 974d0b4e91 Fix retrieved update size from pulseaudio 2009-12-01 12:21:02 -08:00
Chris Robinson d66832a39c Accept a signal only when the pulseaudio stream/context is ready 2009-12-01 12:18:34 -08:00
Chris Robinson d5889a941f Clamp dry gain after cone attenuation is applied 2009-12-01 03:32:04 -08:00
Chris Robinson 6248e986e5 Don't complain if the length given by pulse isn't an exact multiple of the period size 2009-12-01 02:23:38 -08:00
Chris Robinson 786b98a013 Avoid setting a field redundantly 2009-11-29 23:07:04 -08:00
Chris Robinson f63d8dbf38 Enable real-time priority for ALSA, OSS, and DirectSound mixing loops 2009-11-29 23:02:21 -08:00
Chris Robinson 15aad09ce7 Check for the pthread_setschedparam function 2009-11-29 22:44:56 -08:00
Chris Robinson fdd314f7f8 Reset the kill flag after the thread has stopped 2009-11-29 10:22:12 -08:00
Chris Robinson 39b456d88c Add AL_EXT_double tokens to alext.h 2009-11-28 22:19:04 -08:00
Chris Robinson d930fb8d3d Call the Update effect method for null effects 2009-11-28 20:09:41 -08:00
Chris Robinson 3ec64eb0fd Call to the right databuffer function 2009-11-28 19:37:29 -08:00
Chris Robinson d81c9819b8 Remove unnecessary returns 2009-11-28 19:36:05 -08:00
Chris Robinson 98ce1d14c1 Update AL_EXTX_source_distance_model to require explicit enabling
The in-progress spec has been updated to reflect this
2009-11-27 20:05:21 -08:00
Chris Robinson 69f9ab88b9 Send multi-channel sources to auxiliary effect slots
They are downmixed to mono using a volume-preserving scalar, and passed
through a 1-pole low-pass filter (not chained)
2009-11-26 00:39:32 -08:00
Chris Robinson 1a0676f0eb Mark sources for updating when a new context is made from the device 2009-11-25 16:28:19 -08:00
Chris Robinson 658923175f Update source parameters only when they need changing 2009-11-25 16:21:47 -08:00
Chris Robinson 877f4340ba Base air absorption on distance attenuation, try 2 2009-11-24 21:19:11 -08:00
Chris Robinson 35a9ccb41f Revert "Base air absorption on the distance attenuation"
This reverts commit c7c2f9385f.

Fundamentally wrong. The -6dB rolloff is every doubling of the distance, and
the (scaled) -0.05dB rolloff is supposed to be every additional unit.
2009-11-24 01:39:34 -08:00
Chris Robinson c7c2f9385f Base air absorption on the distance attenuation 2009-11-23 16:25:37 -08:00
Chris Robinson d1f3dbb9a1 Make modulation index 0 map to offset 0 2009-11-23 04:14:12 -08:00
Chris Robinson cfb30fe975 Use a 4x4 matrix to transform coordinates 2009-11-23 04:13:51 -08:00
Chris Robinson 2d1b378ef2 Transform all relevant vectors for converting world-space to listener-space 2009-11-22 22:36:20 -08:00
Chris Robinson 06bbee2449 Add a function for 1-pole filtering 2009-11-22 21:20:27 -08:00
Chris Robinson 85bc300dfa ALCAPIENTRY is deprecated in favor of ALC_APIENTRY 2009-11-22 21:15:11 -08:00
Chris Robinson 0662adacb9 Fix alBufferDataStatic extension name in alext.h 2009-11-22 21:12:43 -08:00
Chris Robinson 65a153da6c Update the drivers config file comment 2009-11-22 15:43:05 -08:00
Chris Robinson c5ee010640 The echo should not take energy-attenuated input 2009-11-22 15:37:32 -08:00
Chris Robinson 1b18b4a0ee Allow unlisted backends to stay available when the drivers list ends with , 2009-11-22 01:06:05 -08:00
Chris Robinson 58765aab6b Print available devices before trying to open one 2009-11-19 19:02:16 -08:00
Chris Robinson 1483af1baa Watch for NULL and empty device lists 2009-11-19 18:49:24 -08:00
Chris Robinson 13979793f6 Display supported filters using a comma-separated listing 2009-11-19 18:46:23 -08:00
Chris Robinson 9c228e7625 Be clearer if device opening or context setup fails 2009-11-19 18:25:29 -08:00
Chris Robinson 6a667b36d1 Reorganize and improve the reverb effect
Code supplied by Christopher Fitzgerald. This update also implements the echo
and modulation parameters.
2009-11-19 14:05:04 -08:00
Chris Robinson fe37f1968d Better approximate the wet attenuation model for reverb 2009-11-19 11:06:41 -08:00
Chris Robinson 4565bdd7ce Make sure there's at least a one-sample delay for the echo's first tap 2009-11-19 10:42:41 -08:00
Chris Robinson 5f3c07ca3b Apply the reverb room rolloff factor for EAX reverb too 2009-11-19 10:29:10 -08:00
Chris Robinson 8d1da6a8ca Move NextPowerOf2 to alMain.h 2009-11-19 09:50:15 -08:00
Chris Robinson ff8e09495d Move aluCart2LUTpos to alu.h 2009-11-19 09:24:35 -08:00
Chris Robinson e868eef679 Make sure to set the new echo sample buffer and remove an unused macro 2009-11-18 17:34:08 -08:00
33 changed files with 3054 additions and 1613 deletions
+381 -223
View File
@@ -48,6 +48,9 @@ typedef struct BackendInfo {
BackendFuncs Funcs;
} BackendInfo;
static BackendInfo BackendList[] = {
#ifdef HAVE_PULSEAUDIO
{ "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
#endif
#ifdef HAVE_ALSA
{ "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
#endif
@@ -66,9 +69,6 @@ static BackendInfo BackendList[] = {
#ifdef HAVE_PORTAUDIO
{ "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
#endif
#ifdef HAVE_PULSEAUDIO
{ "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
#endif
{ "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
@@ -208,6 +208,19 @@ static tls_type LocalContext;
// Context Error
static ALCenum g_eLastContextError = ALC_NO_ERROR;
// Default context extensions
static const ALchar alExtList[] =
"AL_EXTX_buffer_sub_data AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 "
"AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET "
"AL_EXTX_sample_buffer_object AL_EXT_source_distance_model "
"AL_LOKI_quadriphonic";
// Mixing Priority Level
ALint RTPrioLevel;
// Resampler Quality
resampler_t DefaultResampler;
///////////////////////////////////////////////////////
@@ -253,12 +266,19 @@ static void alc_init(void)
tls_create(&LocalContext);
RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0);
DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT);
if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN)
DefaultResampler = RESAMPLER_DEFAULT;
devs = GetConfigValue(NULL, "drivers", "");
if(devs[0])
{
int n;
size_t len;
const char *next = devs;
int endlist;
i = 0;
do {
@@ -266,7 +286,11 @@ static void alc_init(void)
next = strchr(devs, ',');
if(!devs[0] || devs[0] == ',')
{
endlist = 0;
continue;
}
endlist = 1;
len = (next ? ((size_t)(next-devs)) : strlen(devs));
for(n = i;BackendList[n].Init;n++)
@@ -274,19 +298,27 @@ static void alc_init(void)
if(len == strlen(BackendList[n].name) &&
strncmp(BackendList[n].name, devs, len) == 0)
{
BackendInfo Bkp = BackendList[i];
BackendList[i] = BackendList[n];
BackendInfo Bkp = BackendList[n];
while(n > i)
{
BackendList[n] = BackendList[n-1];
--n;
}
BackendList[n] = Bkp;
i++;
break;
}
}
} while(next++);
BackendList[i].name = NULL;
BackendList[i].Init = NULL;
BackendList[i].Deinit = NULL;
BackendList[i].Probe = NULL;
if(endlist)
{
BackendList[i].name = NULL;
BackendList[i].Init = NULL;
BackendList[i].Deinit = NULL;
BackendList[i].Probe = NULL;
}
}
for(i = 0;BackendList[i].Init;i++)
@@ -411,6 +443,63 @@ DECL_APPEND_LIST_FUNC(AllDevice)
DECL_APPEND_LIST_FUNC(CaptureDevice)
void al_print(const char *fname, unsigned int line, const char *fmt, ...)
{
const char *fn;
char str[256];
int i;
fn = strrchr(fname, '/');
if(!fn) fn = strrchr(fname, '\\');;
if(!fn) fn = fname;
else fn += 1;
i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
if(i < (int)sizeof(str) && i > 0)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(str+i, sizeof(str)-i, fmt, ap);
va_end(ap);
}
str[sizeof(str)-1] = 0;
fprintf(stderr, "%s", str);
}
void EnableRTPrio(ALint level)
{
ALboolean failed;
#ifdef _WIN32
if(level > 0)
failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
else
failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
#elif defined(HAVE_PTHREAD_SETSCHEDPARAM)
struct sched_param param;
if(level > 0)
{
/* Use the minimum real-time priority possible for now (on Linux this
* should be 1 for SCHED_RR) */
param.sched_priority = sched_get_priority_min(SCHED_RR);
failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, &param);
}
else
{
param.sched_priority = 0;
failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
}
#else
/* Real-time priority not available */
failed = !!level;
#endif
if(failed)
AL_PRINT("Failed to set priority level for thread\n");
}
/*
IsDevice
@@ -457,9 +546,12 @@ static ALCboolean IsContext(ALCcontext *pContext)
Store latest ALC Error
*/
ALCvoid alcSetError(ALenum errorCode)
ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)
{
g_eLastContextError = errorCode;
if(IsDevice(device))
device->LastError = errorCode;
else
g_eLastContextError = errorCode;
}
@@ -545,16 +637,16 @@ static ALvoid InitContext(ALCcontext *pContext)
//Validate pContext
pContext->LastError = AL_NO_ERROR;
pContext->InUse = AL_FALSE;
pContext->Suspended = AL_FALSE;
//Set globals
pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
pContext->SourceDistanceModel = AL_FALSE;
pContext->DopplerFactor = 1.0f;
pContext->DopplerVelocity = 1.0f;
pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
pContext->ExtensionList = "AL_EXTX_buffer_sub_data AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET AL_EXTX_sample_buffer_object AL_EXTX_source_distance_model AL_LOKI_quadriphonic";
aluInitPanning(pContext);
pContext->ExtensionList = alExtList;
}
@@ -586,7 +678,7 @@ ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, AL
if(SampleSize <= 0)
{
alcSetError(ALC_INVALID_VALUE);
alcSetError(NULL, ALC_INVALID_VALUE);
return NULL;
}
@@ -628,13 +720,13 @@ ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, AL
if(!DeviceFound)
{
alcSetError(ALC_INVALID_VALUE);
alcSetError(NULL, ALC_INVALID_VALUE);
free(pDevice);
pDevice = NULL;
}
}
else
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(NULL, ALC_OUT_OF_MEMORY);
return pDevice;
}
@@ -667,7 +759,7 @@ ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
bReturn = ALC_TRUE;
}
else
alcSetError(ALC_INVALID_DEVICE);
alcSetError(pDevice, ALC_INVALID_DEVICE);
return bReturn;
}
@@ -677,7 +769,7 @@ ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
ALCdevice_StartCapture(pDevice);
else
alcSetError(ALC_INVALID_DEVICE);
alcSetError(pDevice, ALC_INVALID_DEVICE);
}
ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
@@ -685,7 +777,7 @@ ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
ALCdevice_StopCapture(pDevice);
else
alcSetError(ALC_INVALID_DEVICE);
alcSetError(pDevice, ALC_INVALID_DEVICE);
}
ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
@@ -693,7 +785,7 @@ ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer,
if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
else
alcSetError(ALC_INVALID_DEVICE);
alcSetError(pDevice, ALC_INVALID_DEVICE);
}
/*
@@ -703,12 +795,18 @@ ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer,
*/
ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
{
ALCenum errorCode;
ALCenum errorCode = ALC_NO_ERROR;
(void)device;
errorCode = g_eLastContextError;
g_eLastContextError = ALC_NO_ERROR;
if(IsDevice(device))
{
errorCode = device->LastError;
device->LastError = ALC_NO_ERROR;
}
else
{
errorCode = g_eLastContextError;
g_eLastContextError = ALC_NO_ERROR;
}
return errorCode;
}
@@ -720,8 +818,10 @@ ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
*/
ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
{
// Not a lot happens here !
(void)pContext;
SuspendContext(NULL);
if(IsContext(pContext))
pContext->Suspended = AL_TRUE;
ProcessContext(NULL);
}
@@ -732,8 +832,10 @@ ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
*/
ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
{
// Not a lot happens here !
(void)pContext;
SuspendContext(NULL);
if(IsContext(pContext))
pContext->Suspended = AL_FALSE;
ProcessContext(NULL);
}
@@ -802,7 +904,7 @@ ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
free(alcDefaultDeviceSpecifier);
alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
if(!alcDefaultDeviceSpecifier)
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
value = alcDefaultDeviceSpecifier;
break;
@@ -811,7 +913,7 @@ ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
alcAllDeviceList : "");
if(!alcDefaultAllDeviceSpecifier)
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
value = alcDefaultAllDeviceSpecifier;
break;
@@ -820,7 +922,7 @@ ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
alcCaptureDeviceList : "");
if(!alcCaptureDefaultDeviceSpecifier)
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
value = alcCaptureDefaultDeviceSpecifier;
break;
@@ -829,7 +931,7 @@ ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
break;
default:
alcSetError(ALC_INVALID_ENUM);
alcSetError(pDevice, ALC_INVALID_ENUM);
break;
}
@@ -844,6 +946,12 @@ ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
*/
ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
{
if(size == 0 || data == NULL)
{
alcSetError(device, ALC_INVALID_VALUE);
return;
}
if(IsDevice(device) && device->IsCaptureDevice)
{
SuspendContext(NULL);
@@ -852,174 +960,134 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
switch (param)
{
case ALC_CAPTURE_SAMPLES:
if ((size) && (data))
*data = ALCdevice_AvailableSamples(device);
else
alcSetError(ALC_INVALID_VALUE);
*data = ALCdevice_AvailableSamples(device);
break;
case ALC_CONNECTED:
if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
*data = device->Connected;
break;
default:
alcSetError(device, ALC_INVALID_ENUM);
break;
}
ProcessContext(NULL);
return;
}
// Playback Device
switch (param)
{
case ALC_MAJOR_VERSION:
*data = alcMajorVersion;
break;
case ALC_MINOR_VERSION:
*data = alcMinorVersion;
break;
case ALC_EFX_MAJOR_VERSION:
*data = alcEFXMajorVersion;
break;
case ALC_EFX_MINOR_VERSION:
*data = alcEFXMinorVersion;
break;
case ALC_MAX_AUXILIARY_SENDS:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = device->NumAuxSends;
break;
case ALC_ATTRIBUTES_SIZE:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = 13;
break;
case ALC_ALL_ATTRIBUTES:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else if (size < 13)
alcSetError(device, ALC_INVALID_VALUE);
else
{
int i = 0;
SuspendContext(NULL);
data[i++] = ALC_FREQUENCY;
data[i++] = device->Frequency;
data[i++] = ALC_REFRESH;
data[i++] = device->Frequency / device->UpdateSize;
data[i++] = ALC_SYNC;
data[i++] = ALC_FALSE;
data[i++] = ALC_MONO_SOURCES;
data[i++] = device->lNumMonoSources;
data[i++] = ALC_STEREO_SOURCES;
data[i++] = device->lNumStereoSources;
data[i++] = ALC_MAX_AUXILIARY_SENDS;
data[i++] = device->NumAuxSends;
data[i++] = 0;
ProcessContext(NULL);
}
break;
case ALC_FREQUENCY:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = device->Frequency;
break;
case ALC_REFRESH:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = device->Frequency / device->UpdateSize;
break;
case ALC_SYNC:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = ALC_FALSE;
break;
case ALC_MONO_SOURCES:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = device->lNumMonoSources;
break;
case ALC_STEREO_SOURCES:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = device->lNumStereoSources;
break;
case ALC_CONNECTED:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = device->Connected;
break;
default:
alcSetError(ALC_INVALID_ENUM);
alcSetError(device, ALC_INVALID_ENUM);
break;
}
ProcessContext(NULL);
}
else
{
if(data)
{
// Playback Device
switch (param)
{
case ALC_MAJOR_VERSION:
if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = alcMajorVersion;
break;
case ALC_MINOR_VERSION:
if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = alcMinorVersion;
break;
case ALC_EFX_MAJOR_VERSION:
if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = alcEFXMajorVersion;
break;
case ALC_EFX_MINOR_VERSION:
if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = alcEFXMinorVersion;
break;
case ALC_MAX_AUXILIARY_SENDS:
if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = (device?device->NumAuxSends:MAX_SENDS);
break;
case ALC_ATTRIBUTES_SIZE:
if(!IsDevice(device))
alcSetError(ALC_INVALID_DEVICE);
else if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = 13;
break;
case ALC_ALL_ATTRIBUTES:
if(!IsDevice(device))
alcSetError(ALC_INVALID_DEVICE);
else if (size < 13)
alcSetError(ALC_INVALID_VALUE);
else
{
int i = 0;
SuspendContext(NULL);
data[i++] = ALC_FREQUENCY;
data[i++] = device->Frequency;
data[i++] = ALC_REFRESH;
data[i++] = device->Frequency / device->UpdateSize;
data[i++] = ALC_SYNC;
data[i++] = ALC_FALSE;
data[i++] = ALC_MONO_SOURCES;
data[i++] = device->lNumMonoSources;
data[i++] = ALC_STEREO_SOURCES;
data[i++] = device->lNumStereoSources;
data[i++] = ALC_MAX_AUXILIARY_SENDS;
data[i++] = device->NumAuxSends;
data[i++] = 0;
ProcessContext(NULL);
}
break;
case ALC_FREQUENCY:
if(!IsDevice(device))
alcSetError(ALC_INVALID_DEVICE);
else if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = device->Frequency;
break;
case ALC_REFRESH:
if(!IsDevice(device))
alcSetError(ALC_INVALID_DEVICE);
else if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = device->Frequency / device->UpdateSize;
break;
case ALC_SYNC:
if(!IsDevice(device))
alcSetError(ALC_INVALID_DEVICE);
else if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = ALC_FALSE;
break;
case ALC_MONO_SOURCES:
if(!IsDevice(device))
alcSetError(ALC_INVALID_DEVICE);
else if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = device->lNumMonoSources;
break;
case ALC_STEREO_SOURCES:
if(!IsDevice(device))
alcSetError(ALC_INVALID_DEVICE);
else if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = device->lNumStereoSources;
break;
case ALC_CONNECTED:
if(!IsDevice(device))
alcSetError(ALC_INVALID_DEVICE);
else if(size <= 0)
alcSetError(ALC_INVALID_VALUE);
else
*data = device->Connected;
break;
default:
alcSetError(ALC_INVALID_ENUM);
break;
}
}
else if(size)
alcSetError(ALC_INVALID_VALUE);
}
return;
}
@@ -1032,8 +1100,6 @@ ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALC
{
ALCboolean bResult = ALC_FALSE;
(void)device;
if (extName)
{
const char *ptr;
@@ -1058,7 +1124,7 @@ ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALC
}
}
else
alcSetError(ALC_INVALID_VALUE);
alcSetError(device, ALC_INVALID_VALUE);
return bResult;
}
@@ -1074,8 +1140,6 @@ ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar
ALCvoid *pFunction = NULL;
ALsizei i = 0;
(void)device;
if (funcName)
{
while(alcFunctions[i].funcName &&
@@ -1084,7 +1148,7 @@ ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar
pFunction = alcFunctions[i].address;
}
else
alcSetError(ALC_INVALID_VALUE);
alcSetError(device, ALC_INVALID_VALUE);
return pFunction;
}
@@ -1100,14 +1164,12 @@ ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enu
ALsizei i = 0;
ALCenum val;
(void)device;
while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
i++;
val = enumeration[i].value;
if(!enumeration[i].enumName)
alcSetError(ALC_INVALID_VALUE);
alcSetError(device, ALC_INVALID_VALUE);
return val;
}
@@ -1129,13 +1191,13 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
{
alcSetError(ALC_INVALID_DEVICE);
alcSetError(device, ALC_INVALID_DEVICE);
ProcessContext(NULL);
return NULL;
}
// Reset Context Last Error code
g_eLastContextError = ALC_NO_ERROR;
device->LastError = ALC_NO_ERROR;
// If a context is already running on the device, stop playback so the
// device attributes can be updated
@@ -1158,11 +1220,12 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
attrIdx = 0;
while(attrList[attrIdx])
{
if(attrList[attrIdx] == ALC_FREQUENCY)
if(attrList[attrIdx] == ALC_FREQUENCY &&
!ConfigValueExists(NULL, "frequency"))
{
freq = attrList[attrIdx + 1];
if(freq == 0)
freq = device->Frequency;
if(freq < 8000)
freq = 8000;
}
if(attrList[attrIdx] == ALC_STEREO_SOURCES)
@@ -1175,7 +1238,8 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
numMono = device->MaxNoOfSources - numStereo;
}
if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS &&
!ConfigValueExists(NULL, "sends"))
{
numSends = attrList[attrIdx + 1];
if(numSends > MAX_SENDS)
@@ -1185,16 +1249,16 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
attrIdx += 2;
}
device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", level);
device->Frequency = GetConfigValueInt(NULL, "frequency", freq);
device->Bs2bLevel = level;
device->Frequency = freq;
device->lNumMonoSources = numMono;
device->lNumStereoSources = numStereo;
device->NumAuxSends = GetConfigValueInt(NULL, "sends", numSends);
device->NumAuxSends = numSends;
}
if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
{
alcSetError(ALC_INVALID_DEVICE);
alcSetError(device, ALC_INVALID_DEVICE);
aluHandleDisconnect(device);
ProcessContext(NULL);
return NULL;
@@ -1214,7 +1278,7 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
{
alcSetError(ALC_INVALID_DEVICE);
alcSetError(device, ALC_INVALID_DEVICE);
aluHandleDisconnect(device);
ProcessContext(context);
ProcessContext(NULL);
@@ -1236,7 +1300,9 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
source->Send[s].WetFilter.filter = 0;
s++;
}
source->NeedsUpdate = AL_TRUE;
}
aluInitPanning(context);
ProcessContext(context);
}
@@ -1259,7 +1325,7 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
if(!temp)
{
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(device, ALC_OUT_OF_MEMORY);
ProcessContext(NULL);
return NULL;
}
@@ -1268,7 +1334,7 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
ALContext = calloc(1, sizeof(ALCcontext));
if(!ALContext)
{
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(device, ALC_OUT_OF_MEMORY);
ProcessContext(NULL);
return NULL;
}
@@ -1277,6 +1343,7 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
ALContext->Device = device;
InitContext(ALContext);
aluInitPanning(ALContext);
ALContext->next = g_pContextList;
g_pContextList = ALContext;
@@ -1354,7 +1421,7 @@ ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
free(context);
}
else
alcSetError(ALC_INVALID_CONTEXT);
alcSetError(NULL, ALC_INVALID_CONTEXT);
}
@@ -1410,7 +1477,7 @@ ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
if (IsContext(pContext))
pDevice = pContext->Device;
else
alcSetError(ALC_INVALID_CONTEXT);
alcSetError(NULL, ALC_INVALID_CONTEXT);
ProcessContext(NULL);
return pDevice;
@@ -1449,7 +1516,7 @@ ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
}
else
{
alcSetError(ALC_INVALID_CONTEXT);
alcSetError(NULL, ALC_INVALID_CONTEXT);
bReturn = AL_FALSE;
}
@@ -1474,7 +1541,7 @@ ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context)
tls_set(LocalContext, context);
else
{
alcSetError(ALC_INVALID_CONTEXT);
alcSetError(NULL, ALC_INVALID_CONTEXT);
bReturn = AL_FALSE;
}
@@ -1484,6 +1551,87 @@ ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context)
}
// Sets the default channel order used by most non-WaveFormatEx-based APIs
void SetDefaultChannelOrder(ALCdevice *device)
{
switch(aluChannelsFromFormat(device->Format))
{
case 1: device->DevChannels[0] = FRONT_CENTER; break;
case 2: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT; break;
case 4: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT;
device->DevChannels[2] = BACK_LEFT;
device->DevChannels[3] = BACK_RIGHT; break;
case 6: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT;
device->DevChannels[2] = BACK_LEFT;
device->DevChannels[3] = BACK_RIGHT;
device->DevChannels[4] = FRONT_CENTER;
device->DevChannels[5] = LFE; break;
case 7: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT;
device->DevChannels[2] = FRONT_CENTER;
device->DevChannels[3] = LFE;
device->DevChannels[4] = BACK_CENTER;
device->DevChannels[5] = SIDE_LEFT;
device->DevChannels[6] = SIDE_RIGHT; break;
case 8: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT;
device->DevChannels[2] = BACK_LEFT;
device->DevChannels[3] = BACK_RIGHT;
device->DevChannels[4] = FRONT_CENTER;
device->DevChannels[5] = LFE;
device->DevChannels[6] = SIDE_LEFT;
device->DevChannels[7] = SIDE_RIGHT; break;
}
}
// Sets the default order used by WaveFormatEx
void SetDefaultWFXChannelOrder(ALCdevice *device)
{
switch(aluChannelsFromFormat(device->Format))
{
case 1: device->DevChannels[0] = FRONT_CENTER; break;
case 2: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT; break;
case 4: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT;
device->DevChannels[2] = BACK_LEFT;
device->DevChannels[3] = BACK_RIGHT; break;
case 6: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT;
device->DevChannels[2] = FRONT_CENTER;
device->DevChannels[3] = LFE;
device->DevChannels[4] = BACK_LEFT;
device->DevChannels[5] = BACK_RIGHT; break;
case 7: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT;
device->DevChannels[2] = FRONT_CENTER;
device->DevChannels[3] = LFE;
device->DevChannels[4] = BACK_CENTER;
device->DevChannels[5] = SIDE_LEFT;
device->DevChannels[6] = SIDE_RIGHT; break;
case 8: device->DevChannels[0] = FRONT_LEFT;
device->DevChannels[1] = FRONT_RIGHT;
device->DevChannels[2] = FRONT_CENTER;
device->DevChannels[3] = LFE;
device->DevChannels[4] = BACK_LEFT;
device->DevChannels[5] = BACK_RIGHT;
device->DevChannels[6] = SIDE_LEFT;
device->DevChannels[7] = SIDE_RIGHT; break;
}
}
static ALenum GetFormatFromString(const char *str)
{
if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
@@ -1536,6 +1684,7 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
//Validate device
device->Connected = ALC_TRUE;
device->IsCaptureDevice = AL_FALSE;
device->LastError = ALC_NO_ERROR;
device->Bs2b = NULL;
device->szDeviceName = NULL;
@@ -1545,8 +1694,8 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
//Set output format
device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
if(device->Frequency == 0)
device->Frequency = SWMIXER_OUTPUT_RATE;
if(device->Frequency < 8000)
device->Frequency = 8000;
fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
device->Format = GetFormatFromString(fmt);
@@ -1579,6 +1728,15 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
if(aluChannelsFromFormat(device->Format) <= 2)
{
device->HeadDampen = GetConfigValueFloat(NULL, "head_dampen", DEFAULT_HEAD_DAMPEN);
device->HeadDampen = __min(device->HeadDampen, 1.0f);
device->HeadDampen = __max(device->HeadDampen, 0.0f);
}
else
device->HeadDampen = 0.0f;
// Find a playback device to open
SuspendContext(NULL);
for(i = 0;BackendList[i].Init;i++)
@@ -1599,13 +1757,13 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
if (!bDeviceFound)
{
// No suitable output device found
alcSetError(ALC_INVALID_VALUE);
alcSetError(NULL, ALC_INVALID_VALUE);
free(device);
device = NULL;
}
}
else
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(NULL, ALC_OUT_OF_MEMORY);
return device;
}
@@ -1689,7 +1847,7 @@ ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
bReturn = ALC_TRUE;
}
else
alcSetError(ALC_INVALID_DEVICE);
alcSetError(pDevice, ALC_INVALID_DEVICE);
return bReturn;
}
+498 -373
View File
File diff suppressed because it is too large Load Diff
+12 -2
View File
@@ -286,7 +286,11 @@ const char *GetConfigValue(const char *blockName, const char *keyName, const cha
for(j = 0;j < cfgBlocks[i].entryCount;j++)
{
if(strcasecmp(cfgBlocks[i].entries[j].key, keyName) == 0)
return cfgBlocks[i].entries[j].value;
{
if(cfgBlocks[i].entries[j].value[0])
return cfgBlocks[i].entries[j].value;
return def;
}
}
}
}
@@ -294,6 +298,12 @@ const char *GetConfigValue(const char *blockName, const char *keyName, const cha
return def;
}
int ConfigValueExists(const char *blockName, const char *keyName)
{
const char *val = GetConfigValue(blockName, keyName, "");
return !!val[0];
}
int GetConfigValueInt(const char *blockName, const char *keyName, int def)
{
const char *val = GetConfigValue(blockName, keyName, "");
@@ -314,7 +324,7 @@ float GetConfigValueFloat(const char *blockName, const char *keyName, float def)
#endif
}
int GetConfigValueBool(const char *blockName, const char *keyName, float def)
int GetConfigValueBool(const char *blockName, const char *keyName, int def)
{
const char *val = GetConfigValue(blockName, keyName, "");
+5 -25
View File
@@ -29,9 +29,6 @@
#include "alError.h"
#include "alu.h"
// Just a soft maximum. Being higher will cause EchoUpdate to reallocate the
// sample buffer which may cause an abort if realloc fails
#define MAX_ECHO_FREQ 192000
typedef struct ALechoState {
// Must be first in all effects!
@@ -56,24 +53,6 @@ typedef struct ALechoState {
ALfloat history[2];
} ALechoState;
// Find the next power of 2. Actually, this will return the input value if
// it is already a power of 2.
static ALuint NextPowerOf2(ALuint value)
{
ALuint powerOf2 = 1;
if(value)
{
value--;
while(value)
{
value >>= 1;
powerOf2 <<= 1;
}
}
return powerOf2;
}
ALvoid EchoDestroy(ALeffectState *effect)
{
ALechoState *state = (ALechoState*)effect;
@@ -92,9 +71,9 @@ ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
// Use the next power of 2 for the buffer length, so the tap offsets can be
// wrapped using a mask instead of a modulo
maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Device->Frequency);
maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Device->Frequency);
maxlen = NextPowerOf2(maxlen+1);
maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Device->Frequency) + 1;
maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1;
maxlen = NextPowerOf2(maxlen);
if(maxlen != state->BufferLength)
{
@@ -106,6 +85,7 @@ ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device)
alSetError(AL_OUT_OF_MEMORY);
return AL_FALSE;
}
state->SampleBuffer = temp;
state->BufferLength = maxlen;
}
for(i = 0;i < state->BufferLength;i++)
@@ -120,7 +100,7 @@ ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffect *Ef
ALuint frequency = Context->Device->Frequency;
ALfloat lrpan, cw, a, g;
state->Tap[0].delay = (ALuint)(Effect->Echo.Delay * frequency);
state->Tap[0].delay = (ALuint)(Effect->Echo.Delay * frequency) + 1;
state->Tap[1].delay = (ALuint)(Effect->Echo.LRDelay * frequency);
state->Tap[1].delay += state->Tap[0].delay;
+877 -391
View File
File diff suppressed because it is too large Load Diff
+61 -55
View File
@@ -92,6 +92,7 @@ MAKE_FUNC(snd_pcm_mmap_commit);
MAKE_FUNC(snd_pcm_readi);
MAKE_FUNC(snd_pcm_writei);
MAKE_FUNC(snd_pcm_drain);
MAKE_FUNC(snd_pcm_recover);
MAKE_FUNC(snd_pcm_info_malloc);
MAKE_FUNC(snd_pcm_info_free);
MAKE_FUNC(snd_pcm_info_set_device);
@@ -118,7 +119,7 @@ static ALuint numCaptureDevNames;
static volatile ALuint load_count;
void alsa_load(void)
void *alsa_load(void)
{
if(load_count == 0)
{
@@ -127,7 +128,7 @@ void alsa_load(void)
#ifdef HAVE_DLFCN_H
alsa_handle = dlopen("libasound.so.2", RTLD_NOW);
if(!alsa_handle)
return;
return NULL;
dlerror();
#define LOAD_FUNC(f) do { \
@@ -137,7 +138,7 @@ void alsa_load(void)
dlclose(alsa_handle); \
alsa_handle = NULL; \
AL_PRINT("Could not load %s from libasound.so.2: %s\n", #f, str); \
return; \
return NULL; \
} \
} while(0)
#else
@@ -185,6 +186,7 @@ LOAD_FUNC(snd_pcm_mmap_commit);
LOAD_FUNC(snd_pcm_readi);
LOAD_FUNC(snd_pcm_writei);
LOAD_FUNC(snd_pcm_drain);
LOAD_FUNC(snd_pcm_recover);
LOAD_FUNC(snd_pcm_info_malloc);
LOAD_FUNC(snd_pcm_info_free);
@@ -205,6 +207,8 @@ LOAD_FUNC(snd_card_next);
#undef LOAD_FUNC
}
++load_count;
return alsa_handle;
}
void alsa_unload(void)
@@ -221,22 +225,13 @@ void alsa_unload(void)
static int xrun_recovery(snd_pcm_t *handle, int err)
{
if (err == -EPIPE)
{ /* under-run */
err = psnd_pcm_prepare(handle);
if (err < 0)
AL_PRINT("prepare failed: %s\n", psnd_strerror(err));
}
else if (err == -ESTRPIPE)
if(err == -EINTR || err == -EPIPE || err == -ESTRPIPE)
{
while ((err = psnd_pcm_resume(handle)) == -EAGAIN)
Sleep(1); /* wait until the suspend flag is released */
if (err < 0)
{
err = psnd_pcm_recover(handle, err, 1);
if(err >= 0)
err = psnd_pcm_prepare(handle);
if (err < 0)
AL_PRINT("prepare failed: %s\n", psnd_strerror(err));
}
if(err < 0)
AL_PRINT("recover failed: %s\n", psnd_strerror(err));
}
return err;
}
@@ -271,6 +266,8 @@ static ALuint ALSAProc(ALvoid *ptr)
char *WritePtr;
int err;
EnableRTPrio(RTPrioLevel);
while(!data->killNow)
{
int state = verify_state(data->pcmHandle);
@@ -343,6 +340,8 @@ static ALuint ALSANoMMapProc(ALvoid *ptr)
snd_pcm_sframes_t avail;
char *WritePtr;
EnableRTPrio(RTPrioLevel);
while(!data->killNow)
{
int state = verify_state(data->pcmHandle);
@@ -365,10 +364,11 @@ static ALuint ALSANoMMapProc(ALvoid *ptr)
case -EAGAIN:
continue;
case -ESTRPIPE:
while((ret=psnd_pcm_resume(data->pcmHandle)) == -EAGAIN)
Sleep(1);
break;
case -EPIPE:
case -EINTR:
ret = psnd_pcm_recover(data->pcmHandle, ret, 1);
if(ret >= 0)
psnd_pcm_prepare(data->pcmHandle);
break;
default:
if (ret >= 0)
@@ -396,6 +396,8 @@ static ALuint ALSANoMMapCaptureProc(ALvoid *ptr)
alsa_data *data = (alsa_data*)pDevice->ExtraData;
snd_pcm_sframes_t avail;
EnableRTPrio(RTPrioLevel);
while(!data->killNow)
{
int state = verify_state(data->pcmHandle);
@@ -413,10 +415,11 @@ static ALuint ALSANoMMapCaptureProc(ALvoid *ptr)
case -EAGAIN:
continue;
case -ESTRPIPE:
while((avail=psnd_pcm_resume(data->pcmHandle)) == -EAGAIN)
Sleep(1);
break;
case -EPIPE:
case -EINTR:
avail = psnd_pcm_recover(data->pcmHandle, avail, 1);
if(avail >= 0)
psnd_pcm_prepare(data->pcmHandle);
break;
default:
if (avail >= 0 && data->doCapture)
@@ -462,8 +465,7 @@ static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceNam
return ALC_FALSE;
}
alsa_load();
if(!alsa_handle)
if(!alsa_load())
return ALC_FALSE;
data = (alsa_data*)calloc(1, sizeof(alsa_data));
@@ -546,14 +548,14 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
if((i=psnd_pcm_hw_params_any(data->pcmHandle, p)) < 0)
err = "any";
/* set interleaved access */
if(err == NULL && (!allowmmap || (i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0))
if(i >= 0 && (!allowmmap || (i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0))
{
if(periods > 2) periods--;
if((i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
err = "set access";
}
/* set format (implicitly sets sample bits) */
if(err == NULL && (i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0)
{
switch(aluChannelsFromFormat(device->Format))
{
@@ -592,7 +594,7 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
}
}
/* set channels (implicitly sets frame bits) */
if(err == NULL && (i=psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(device->Format))) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(device->Format))) < 0)
{
switch(aluBytesFromFormat(device->Format))
{
@@ -613,24 +615,24 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
}
}
/* set periods (implicitly constrains period/buffer parameters) */
if(err == NULL && (i=psnd_pcm_hw_params_set_periods_near(data->pcmHandle, p, &periods, NULL)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_periods_near(data->pcmHandle, p, &periods, NULL)) < 0)
err = "set periods near";
/* set rate (implicitly constrains period/buffer parameters) */
if(err == NULL && (i=psnd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &rate, NULL)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &rate, NULL)) < 0)
err = "set rate near";
/* set period size in frame units (implicitly sets buffer size/bytes/time and period time/bytes) */
if(err == NULL && (i=psnd_pcm_hw_params_set_period_size_near(data->pcmHandle, p, &periodSizeInFrames, NULL)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_period_size_near(data->pcmHandle, p, &periodSizeInFrames, NULL)) < 0)
err = "set period size near";
/* install and prepare hardware configuration */
if(err == NULL && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0)
err = "set params";
if(err == NULL && (i=psnd_pcm_hw_params_get_access(p, &access)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_get_access(p, &access)) < 0)
err = "get access";
if(err == NULL && (i=psnd_pcm_hw_params_get_period_size(p, &periodSizeInFrames, NULL)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_get_period_size(p, &periodSizeInFrames, NULL)) < 0)
err = "get period size";
if(err == NULL && (i=psnd_pcm_hw_params_get_periods(p, &periods, NULL)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_get_periods(p, &periods, NULL)) < 0)
err = "get periods";
if(err != NULL)
if(i < 0)
{
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
psnd_pcm_hw_params_free(p);
@@ -644,11 +646,11 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
if((i=psnd_pcm_sw_params_current(data->pcmHandle, sp)) != 0)
err = "sw current";
if(err == NULL && (i=psnd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)) != 0)
if(i == 0 && (i=psnd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)) != 0)
err = "sw set avail min";
if(err == NULL && (i=psnd_pcm_sw_params(data->pcmHandle, sp)) != 0)
if(i == 0 && (i=psnd_pcm_sw_params(data->pcmHandle, sp)) != 0)
err = "sw set params";
if(err != NULL)
if(i != 0)
{
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
psnd_pcm_sw_params_free(sp);
@@ -657,6 +659,8 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
psnd_pcm_sw_params_free(sp);
SetDefaultChannelOrder(device);
data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames);
if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
{
@@ -669,6 +673,9 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
AL_PRINT("buffer malloc failed\n");
return ALC_FALSE;
}
device->UpdateSize = periodSizeInFrames;
device->NumUpdates = periods;
device->Frequency = rate;
data->thread = StartThread(ALSANoMMapProc, device);
}
else
@@ -679,6 +686,9 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
AL_PRINT("prepare error: %s\n", psnd_strerror(i));
return ALC_FALSE;
}
device->UpdateSize = periodSizeInFrames;
device->NumUpdates = periods;
device->Frequency = rate;
data->thread = StartThread(ALSAProc, device);
}
if(data->thread == NULL)
@@ -689,10 +699,6 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
return ALC_FALSE;
}
device->UpdateSize = periodSizeInFrames;
device->NumUpdates = periods;
device->Frequency = rate;
return ALC_TRUE;
}
@@ -706,6 +712,7 @@ static void alsa_stop_playback(ALCdevice *device)
StopThread(data->thread);
data->thread = NULL;
}
data->killNow = 0;
free(data->buffer);
data->buffer = NULL;
}
@@ -746,8 +753,7 @@ static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceNam
return ALC_FALSE;
}
alsa_load();
if(!alsa_handle)
if(!alsa_load())
return ALC_FALSE;
data = (alsa_data*)calloc(1, sizeof(alsa_data));
@@ -795,24 +801,24 @@ static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceNam
if((i=psnd_pcm_hw_params_any(data->pcmHandle, p)) < 0)
err = "any";
/* set interleaved access */
if(err == NULL && (i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
err = "set access";
/* set format (implicitly sets sample bits) */
if(err == NULL && (i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0)
err = "set format";
/* set channels (implicitly sets frame bits) */
if(err == NULL && (i=psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(pDevice->Format))) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(pDevice->Format))) < 0)
err = "set channels";
/* set rate (implicitly constrains period/buffer parameters) */
if(err == NULL && (i=psnd_pcm_hw_params_set_rate(data->pcmHandle, p, pDevice->Frequency, 0)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_rate(data->pcmHandle, p, pDevice->Frequency, 0)) < 0)
err = "set rate near";
/* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
if(err == NULL && (i=psnd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames)) < 0)
err = "set buffer size near";
/* install and prepare hardware configuration */
if(err == NULL && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0)
if(i >= 0 && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0)
err = "set params";
if(err != NULL)
if(i < 0)
{
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
psnd_pcm_hw_params_free(p);
@@ -904,7 +910,7 @@ static void alsa_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint l
if(lSamples <= (ALCuint)RingBufferSize(data->ring))
ReadRingBuffer(data->ring, pBuffer, lSamples);
else
alcSetError(ALC_INVALID_VALUE);
alcSetError(pDevice, ALC_INVALID_VALUE);
}
static ALCuint alsa_available_samples(ALCdevice *pDevice)
@@ -959,8 +965,8 @@ void alc_alsa_probe(int type)
char name[128];
ALuint i;
alsa_load();
if(!alsa_handle) return;
if(!alsa_load())
return;
psnd_ctl_card_info_malloc(&info);
psnd_pcm_info_malloc(&pcminfo);
+15 -12
View File
@@ -74,7 +74,7 @@ static ALuint NumDevices;
static volatile ALuint load_count;
void DSoundLoad(void)
void *DSoundLoad(void)
{
if(load_count == 0)
{
@@ -83,7 +83,7 @@ void DSoundLoad(void)
if(ds_handle == NULL)
{
AL_PRINT("Failed to load dsound.dll\n");
return;
return NULL;
}
#define LOAD_FUNC(f) do { \
@@ -93,7 +93,7 @@ void DSoundLoad(void)
FreeLibrary(ds_handle); \
ds_handle = NULL; \
AL_PRINT("Could not load %s from dsound.dll\n", #f); \
return; \
return NULL; \
} \
} while(0)
#else
@@ -106,6 +106,8 @@ LOAD_FUNC(DirectSoundEnumerateA);
#undef LOAD_FUNC
}
++load_count;
return ds_handle;
}
void DSoundUnload(void)
@@ -134,6 +136,8 @@ static ALuint DSoundProc(ALvoid *ptr)
DWORD avail;
HRESULT err;
EnableRTPrio(RTPrioLevel);
memset(&DSBCaps, 0, sizeof(DSBCaps));
DSBCaps.dwSize = sizeof(DSBCaps);
err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps);
@@ -221,8 +225,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
return ALC_FALSE;
}
DSoundLoad();
if(ds_handle == NULL)
if(!DSoundLoad())
return ALC_FALSE;
//Initialise requested device
@@ -230,7 +233,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
pData = calloc(1, sizeof(DSoundData));
if(!pData)
{
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(device, ALC_OUT_OF_MEMORY);
DSoundUnload();
return ALC_FALSE;
}
@@ -277,7 +280,7 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
memset(&OutputType, 0, sizeof(OutputType));
hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers);
if(SUCCEEDED(hr) && *(GetConfigValue(NULL, "format", "")) != 0)
if(SUCCEEDED(hr) && ConfigValueExists(NULL, "format"))
{
if(aluChannelsFromFormat(device->Format) == 1)
speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0);
@@ -412,7 +415,8 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
if(SUCCEEDED(hr))
{
device->ExtraData = pData;
device->Format = format;
SetDefaultWFXChannelOrder(device);
pData->thread = StartThread(DSoundProc, device);
if(!pData->thread)
hr = E_FAIL;
@@ -429,8 +433,6 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
return ALC_FALSE;
}
device->Format = format;
return ALC_TRUE;
}
@@ -445,6 +447,8 @@ static void DSoundStopPlayback(ALCdevice *device)
StopThread(pData->thread);
pData->thread = NULL;
pData->killNow = 0;
IDirectSoundBuffer_Release(pData->DSsbuffer);
pData->DSsbuffer = NULL;
if (pData->DSpbuffer)
@@ -547,8 +551,7 @@ void alcDSoundDeinit(void)
void alcDSoundProbe(int type)
{
DSoundLoad();
if(!ds_handle) return;
if(!DSoundLoad()) return;
if(type == DEVICE_PROBE)
AppendDeviceList(dsDevice);
+36 -9
View File
@@ -82,6 +82,8 @@ static ALuint OSSProc(ALvoid *ptr)
ALint frameSize;
ssize_t wrote;
EnableRTPrio(RTPrioLevel);
frameSize = aluChannelsFromFormat(pDevice->Format) *
aluBytesFromFormat(pDevice->Format);
@@ -100,10 +102,10 @@ static ALuint OSSProc(ALvoid *ptr)
{
AL_PRINT("write failed: %s\n", strerror(errno));
aluHandleDisconnect(pDevice);
len = 0;
break;
}
else
Sleep(1);
Sleep(1);
continue;
}
@@ -122,6 +124,8 @@ static ALuint OSSCaptureProc(ALvoid *ptr)
int frameSize;
int amt;
EnableRTPrio(RTPrioLevel);
frameSize = aluBytesFromFormat(pDevice->Format);
frameSize *= aluChannelsFromFormat(pDevice->Format);
@@ -165,7 +169,8 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
if(data->fd == -1)
{
free(data);
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
if(errno != ENOENT)
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
return ALC_FALSE;
}
@@ -270,6 +275,8 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
data->data_size = device->UpdateSize * frameSize;
data->mix_data = calloc(1, data->data_size);
SetDefaultChannelOrder(device);
data->thread = StartThread(OSSProc, device);
if(data->thread == NULL)
{
@@ -292,6 +299,7 @@ static void oss_stop_playback(ALCdevice *device)
StopThread(data->thread);
data->thread = NULL;
data->killNow = 0;
if(ioctl(data->fd, SNDCTL_DSP_RESET) != 0)
AL_PRINT("Error resetting device: %s\n", strerror(errno));
@@ -329,7 +337,8 @@ static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName)
if(data->fd == -1)
{
free(data);
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
if(errno != ENOENT)
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
return ALC_FALSE;
}
@@ -450,7 +459,7 @@ static void oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lS
if(lSamples <= (ALCuint)RingBufferSize(data->ring))
ReadRingBuffer(data->ring, pBuffer, lSamples);
else
alcSetError(ALC_INVALID_VALUE);
alcSetError(pDevice, ALC_INVALID_VALUE);
}
static ALCuint oss_available_samples(ALCdevice *pDevice)
@@ -485,9 +494,27 @@ void alc_oss_deinit(void)
void alc_oss_probe(int type)
{
if(type == DEVICE_PROBE)
AppendDeviceList(oss_device);
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0)
#endif
AppendDeviceList(oss_device);
}
else if(type == ALL_DEVICE_PROBE)
AppendAllDeviceList(oss_device);
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0)
#endif
AppendAllDeviceList(oss_device);
}
else if(type == CAPTURE_DEVICE_PROBE)
AppendCaptureDeviceList(oss_device_capture);
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(GetConfigValue("oss", "capture", "/dev/dsp"), &buf) == 0)
#endif
AppendCaptureDeviceList(oss_device_capture);
}
}
+26 -26
View File
@@ -50,7 +50,7 @@ static const ALCchar pa_device[] = "PortAudio Software";
static volatile ALuint load_count;
void pa_load(void)
void *pa_load(void)
{
const char *str;
PaError err;
@@ -65,7 +65,7 @@ void pa_load(void)
#endif
pa_handle = dlopen(PALIB, RTLD_NOW);
if(!pa_handle)
return;
return NULL;
dlerror();
#define LOAD_FUNC(f) do { \
@@ -75,7 +75,7 @@ void pa_load(void)
dlclose(pa_handle); \
pa_handle = NULL; \
AL_PRINT("Could not load %s from "PALIB": %s\n", #f, str); \
return; \
return NULL; \
} \
} while(0)
#else
@@ -103,11 +103,12 @@ LOAD_FUNC(Pa_GetStreamInfo);
dlclose(pa_handle);
#endif
pa_handle = NULL;
return;
return NULL;
}
}
++load_count;
return pa_handle;
}
void pa_unload(void)
@@ -155,8 +156,7 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
else if(strcmp(deviceName, pa_device) != 0)
return ALC_FALSE;
pa_load();
if(pa_handle == NULL)
if(!pa_load())
return ALC_FALSE;
data = (pa_data*)calloc(1, sizeof(pa_data));
@@ -189,6 +189,8 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
}
outParams.channelCount = aluChannelsFromFormat(device->Format);
SetDefaultChannelOrder(device);
err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
device->UpdateSize, paNoFlag, pa_callback, device);
if(err != paNoError)
@@ -201,19 +203,9 @@ static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
}
streamInfo = pPa_GetStreamInfo(data->stream);
err = pPa_StartStream(data->stream);
if(err != paNoError)
{
AL_PRINT("Pa_StartStream() returned an error: %s\n", pPa_GetErrorText(err));
pPa_CloseStream(data->stream);
device->ExtraData = NULL;
free(data);
pa_unload();
return ALC_FALSE;
}
device->szDeviceName = strdup(deviceName);
device->Frequency = streamInfo->sampleRate;
return ALC_TRUE;
}
@@ -222,13 +214,9 @@ static void pa_close_playback(ALCdevice *device)
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_StopStream(data->stream);
if(err != paNoError)
fprintf(stderr, "Error stopping stream: %s\n", pPa_GetErrorText(err));
err = pPa_CloseStream(data->stream);
if(err != paNoError)
fprintf(stderr, "Error closing stream: %s\n", pPa_GetErrorText(err));
AL_PRINT("Error closing stream: %s\n", pPa_GetErrorText(err));
free(data);
device->ExtraData = NULL;
@@ -240,16 +228,29 @@ static ALCboolean pa_reset_playback(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
const PaStreamInfo *streamInfo;
PaError err;
streamInfo = pPa_GetStreamInfo(data->stream);
device->Frequency = streamInfo->sampleRate;
err = pPa_StartStream(data->stream);
if(err != paNoError)
{
AL_PRINT("Pa_StartStream() returned an error: %s\n", pPa_GetErrorText(err));
return ALC_FALSE;
}
return ALC_TRUE;
}
static void pa_stop_playback(ALCdevice *device)
{
(void)device;
pa_data *data = (pa_data*)device->ExtraData;
PaError err;
err = pPa_StopStream(data->stream);
if(err != paNoError)
AL_PRINT("Error stopping stream: %s\n", pPa_GetErrorText(err));
}
@@ -286,8 +287,7 @@ void alc_pa_deinit(void)
void alc_pa_probe(int type)
{
pa_load();
if(!pa_handle) return;
if(!pa_load()) return;
if(type == DEVICE_PROBE)
AppendDeviceList(pa_device);
+323 -125
View File
@@ -44,6 +44,13 @@ static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x)
#error Invalid PulseAudio API version
#endif
#ifndef PA_CHECK_VERSION
#define PA_CHECK_VERSION(major,minor,micro) \
((PA_MAJOR > (major)) || \
(PA_MAJOR == (major) && PA_MINOR > (minor)) || \
(PA_MAJOR == (major) && PA_MINOR == (minor) && PA_MICRO >= (micro)))
#endif
static void *pa_handle;
#define MAKE_FUNC(x) static typeof(x) * p##x
MAKE_FUNC(pa_context_unref);
@@ -67,18 +74,21 @@ MAKE_FUNC(pa_stream_write);
MAKE_FUNC(pa_xfree);
MAKE_FUNC(pa_stream_connect_record);
MAKE_FUNC(pa_stream_connect_playback);
MAKE_FUNC(pa_stream_readable_size);
MAKE_FUNC(pa_stream_cork);
MAKE_FUNC(pa_path_get_filename);
MAKE_FUNC(pa_get_binary_name);
MAKE_FUNC(pa_threaded_mainloop_free);
MAKE_FUNC(pa_context_errno);
MAKE_FUNC(pa_xmalloc0);
MAKE_FUNC(pa_xmalloc);
MAKE_FUNC(pa_stream_unref);
MAKE_FUNC(pa_threaded_mainloop_accept);
MAKE_FUNC(pa_stream_set_write_callback);
MAKE_FUNC(pa_threaded_mainloop_new);
MAKE_FUNC(pa_context_connect);
MAKE_FUNC(pa_stream_set_buffer_attr);
MAKE_FUNC(pa_stream_get_buffer_attr);
MAKE_FUNC(pa_stream_set_buffer_attr_callback);
MAKE_FUNC(pa_stream_get_sample_spec);
MAKE_FUNC(pa_stream_set_read_callback);
MAKE_FUNC(pa_stream_set_state_callback);
MAKE_FUNC(pa_stream_new);
@@ -86,6 +96,18 @@ MAKE_FUNC(pa_stream_disconnect);
MAKE_FUNC(pa_threaded_mainloop_lock);
MAKE_FUNC(pa_channel_map_init_auto);
MAKE_FUNC(pa_channel_map_parse);
MAKE_FUNC(pa_channel_map_snprint);
MAKE_FUNC(pa_channel_map_superset);
MAKE_FUNC(pa_context_get_server_info);
MAKE_FUNC(pa_context_get_sink_info_by_name);
MAKE_FUNC(pa_operation_get_state);
MAKE_FUNC(pa_operation_unref);
#if PA_CHECK_VERSION(0,9,15)
MAKE_FUNC(pa_stream_set_buffer_attr_callback);
#endif
#if PA_CHECK_VERSION(0,9,16)
MAKE_FUNC(pa_stream_begin_write);
#endif
#undef MAKE_FUNC
#ifndef PATH_MAX
@@ -113,10 +135,11 @@ typedef struct {
static const ALCchar pulse_device[] = "PulseAudio Software";
static const ALCchar pulse_capture_device[] = "PulseAudio Capture";
static pa_context_flags_t pulse_ctx_flags;
static volatile ALuint load_count;
void pulse_load(void) //{{{
void *pulse_load(void) //{{{
{
if(load_count == 0)
{
@@ -128,9 +151,12 @@ void pulse_load(void) //{{{
AL_PRINT("Could not load %s from libpulse-0.dll\n", #x); \
FreeLibrary(pa_handle); \
pa_handle = NULL; \
return; \
return NULL; \
} \
} while(0)
#define LOAD_OPTIONAL_FUNC(x) do { \
p##x = GetProcAddress(pa_handle, #x); \
} while(0)
#elif defined (HAVE_DLFCN_H)
@@ -148,7 +174,13 @@ void pulse_load(void) //{{{
AL_PRINT("Could not load %s from libpulse: %s\n", #x, err); \
dlclose(pa_handle); \
pa_handle = NULL; \
return; \
return NULL; \
} \
} while(0)
#define LOAD_OPTIONAL_FUNC(x) do { \
p##x = dlsym(pa_handle, #x); \
if((err=dlerror()) != NULL) { \
p##x = NULL; \
} \
} while(0)
@@ -156,10 +188,11 @@ void pulse_load(void) //{{{
pa_handle = (void*)0xDEADBEEF;
#define LOAD_FUNC(x) p##x = (x)
#define LOAD_OPTIONAL_FUNC(x) p##x = (x)
#endif
if(!pa_handle)
return;
return NULL;
LOAD_FUNC(pa_context_unref);
LOAD_FUNC(pa_sample_spec_valid);
@@ -182,18 +215,21 @@ LOAD_FUNC(pa_stream_write);
LOAD_FUNC(pa_xfree);
LOAD_FUNC(pa_stream_connect_record);
LOAD_FUNC(pa_stream_connect_playback);
LOAD_FUNC(pa_stream_readable_size);
LOAD_FUNC(pa_stream_cork);
LOAD_FUNC(pa_path_get_filename);
LOAD_FUNC(pa_get_binary_name);
LOAD_FUNC(pa_threaded_mainloop_free);
LOAD_FUNC(pa_context_errno);
LOAD_FUNC(pa_xmalloc0);
LOAD_FUNC(pa_xmalloc);
LOAD_FUNC(pa_stream_unref);
LOAD_FUNC(pa_threaded_mainloop_accept);
LOAD_FUNC(pa_stream_set_write_callback);
LOAD_FUNC(pa_threaded_mainloop_new);
LOAD_FUNC(pa_context_connect);
LOAD_FUNC(pa_stream_set_buffer_attr);
LOAD_FUNC(pa_stream_get_buffer_attr);
LOAD_FUNC(pa_stream_set_buffer_attr_callback);
LOAD_FUNC(pa_stream_get_sample_spec);
LOAD_FUNC(pa_stream_set_read_callback);
LOAD_FUNC(pa_stream_set_state_callback);
LOAD_FUNC(pa_stream_new);
@@ -201,10 +237,25 @@ LOAD_FUNC(pa_stream_disconnect);
LOAD_FUNC(pa_threaded_mainloop_lock);
LOAD_FUNC(pa_channel_map_init_auto);
LOAD_FUNC(pa_channel_map_parse);
LOAD_FUNC(pa_channel_map_snprint);
LOAD_FUNC(pa_channel_map_superset);
LOAD_FUNC(pa_context_get_server_info);
LOAD_FUNC(pa_context_get_sink_info_by_name);
LOAD_FUNC(pa_operation_get_state);
LOAD_FUNC(pa_operation_unref);
#if PA_CHECK_VERSION(0,9,15)
LOAD_OPTIONAL_FUNC(pa_stream_set_buffer_attr_callback);
#endif
#if PA_CHECK_VERSION(0,9,16)
LOAD_OPTIONAL_FUNC(pa_stream_begin_write);
#endif
#undef LOAD_OPTIONAL_FUNC
#undef LOAD_FUNC
}
++load_count;
return pa_handle;
} //}}}
void pulse_unload(void) //{{{
@@ -226,20 +277,22 @@ static void context_state_callback(pa_context *context, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
(void)context;
pa_context_state_t state;
if(ppa_threaded_mainloop_in_thread(data->loop))
ppa_threaded_mainloop_signal(data->loop, 1);
state = ppa_context_get_state(context);
if(state == PA_CONTEXT_READY || !PA_CONTEXT_IS_GOOD(state))
ppa_threaded_mainloop_signal(data->loop, 0);
}//}}}
static void stream_state_callback(pa_stream *stream, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
(void)stream;
pa_stream_state_t state;
if(ppa_threaded_mainloop_in_thread(data->loop))
ppa_threaded_mainloop_signal(data->loop, 1);
state = ppa_stream_get_state(stream);
if(state == PA_STREAM_READY || !PA_STREAM_IS_GOOD(state))
ppa_threaded_mainloop_signal(data->loop, 0);
}//}}}
static void stream_buffer_attr_callback(pa_stream *stream, void *pdata) //{{{
@@ -250,10 +303,10 @@ static void stream_buffer_attr_callback(pa_stream *stream, void *pdata) //{{{
SuspendContext(NULL);
data->attr = *(ppa_stream_get_buffer_attr(stream));
if((data->attr.tlength%data->attr.minreq) != 0)
AL_PRINT("new tlength (%d) is not a multiple of minreq (%d)!\n",
if(data->attr.tlength < data->attr.minreq*2)
AL_PRINT("new tlength (%d) is smaller than two periods (%d x 2)!\n",
data->attr.tlength, data->attr.minreq);
Device->UpdateSize = data->attr.minreq;
Device->UpdateSize = data->attr.minreq / data->frame_size;
Device->NumUpdates = data->attr.tlength/data->attr.minreq;
ProcessContext(NULL);
@@ -262,25 +315,94 @@ static void stream_buffer_attr_callback(pa_stream *stream, void *pdata) //{{{
static void context_state_callback2(pa_context *context, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
if(ppa_context_get_state(context) == PA_CONTEXT_FAILED)
{
AL_PRINT("Received context failure!\n");
aluHandleDisconnect(Device);
}
ppa_threaded_mainloop_signal(data->loop, 0);
}//}}}
static void stream_state_callback2(pa_stream *stream, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
if(ppa_stream_get_state(stream) == PA_STREAM_FAILED)
{
AL_PRINT("Received stream failure!\n");
aluHandleDisconnect(Device);
}
ppa_threaded_mainloop_signal(data->loop, 0);
}//}}}
static void stream_success_callback(pa_stream *stream, int success, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
(void)stream;
(void)success;
ppa_threaded_mainloop_signal(data->loop, 0);
}//}}}
static void server_info_callback(pa_context *context, const pa_server_info *info, void *pdata) //{{{
{
struct {
pa_threaded_mainloop *loop;
char *name;
} *data = pdata;
(void)context;
data->name = strdup(info->default_sink_name);
ppa_threaded_mainloop_signal(data->loop, 0);
}//}}}
static void sink_info_callback(pa_context *context, const pa_sink_info *info, int eol, void *pdata) //{{{
{
ALCdevice *device = pdata;
pulse_data *data = device->ExtraData;
char chanmap_str[256] = "";
const struct {
const char *str;
ALenum format;
} chanmaps[] = {
{ "front-left,front-right,front-center,lfe,rear-left,rear-right,side-left,side-right",
AL_FORMAT_71CHN32 },
{ "front-left,front-right,front-center,lfe,rear-center,side-left,side-right",
AL_FORMAT_61CHN32 },
{ "front-left,front-right,front-center,lfe,rear-left,rear-right",
AL_FORMAT_51CHN32 },
{ "front-left,front-right,rear-left,rear-right", AL_FORMAT_QUAD32 },
{ "front-left,front-right", AL_FORMAT_STEREO_FLOAT32 },
{ "mono", AL_FORMAT_MONO_FLOAT32 },
{ NULL, 0 }
};
int i;
(void)context;
if(eol)
{
ppa_threaded_mainloop_signal(data->loop, 0);
return;
}
for(i = 0;chanmaps[i].str;i++)
{
pa_channel_map map;
if(ppa_channel_map_parse(&map, chanmaps[i].str) &&
ppa_channel_map_superset(&info->channel_map, &map))
{
device->Format = chanmaps[i].format;
return;
}
}
ppa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map);
AL_PRINT("Failed to find format for channel map:\n %s\n", chanmap_str);
}//}}}
//}}}
// PulseAudio I/O Callbacks //{{{
@@ -292,44 +414,31 @@ static void stream_write_callback(pa_stream *stream, size_t len, void *pdata) //
len -= len%data->attr.minreq;
if(len > 0)
{
void *buf = ppa_xmalloc0(len);
void *buf;
pa_free_cb_t free_func = NULL;
#if PA_CHECK_VERSION(0,9,16)
if(!ppa_stream_begin_write ||
ppa_stream_begin_write(stream, &buf, &len) < 0)
#endif
{
buf = ppa_xmalloc(len);
free_func = ppa_xfree;
}
aluMixData(Device, buf, len/data->frame_size);
ppa_stream_write(stream, buf, len, ppa_xfree, 0, PA_SEEK_RELATIVE);
ppa_stream_write(stream, buf, len, free_func, 0, PA_SEEK_RELATIVE);
}
} //}}}
static void stream_read_callback(pa_stream *stream, size_t length, void *pdata) //{{{
{
ALCdevice *Device = pdata;
pulse_data *data = Device->ExtraData;
const void *buf;
if(ppa_stream_peek(stream, &buf, &length) < 0)
{
AL_PRINT("pa_stream_peek() failed: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
return;
}
assert(buf);
assert(length);
length /= data->frame_size;
if(data->samples < length)
AL_PRINT("stream_read_callback: buffer overflow!\n");
WriteRingBuffer(data->ring, buf, (length<data->samples) ? length : data->samples);
ppa_stream_drop(stream);
} //}}}
//}}}
static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{{
{
pulse_data *data = ppa_xmalloc0(sizeof(pulse_data));
pulse_data *data = ppa_xmalloc(sizeof(pulse_data));
pa_context_state_t state;
memset(data, 0, sizeof(*data));
if(ppa_get_binary_name(data->path_name, sizeof(data->path_name)))
data->context_name = ppa_path_get_filename(data->path_name);
else
@@ -353,8 +462,7 @@ static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{
data->context = ppa_context_new(ppa_threaded_mainloop_get_api(data->loop), data->context_name);
if(!data->context)
{
AL_PRINT("pa_context_new() failed: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
AL_PRINT("pa_context_new() failed\n");
ppa_threaded_mainloop_unlock(data->loop);
goto out;
@@ -362,7 +470,7 @@ static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{
ppa_context_set_state_callback(data->context, context_state_callback, device);
if(ppa_context_connect(data->context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0)
if(ppa_context_connect(data->context, NULL, pulse_ctx_flags, NULL) < 0)
{
AL_PRINT("Context did not connect: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
@@ -378,8 +486,9 @@ static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{
{
if(!PA_CONTEXT_IS_GOOD(state))
{
AL_PRINT("Context did not get ready: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
int err = ppa_context_errno(data->context);
if(err != PA_ERR_CONNECTIONREFUSED)
AL_PRINT("Context did not get ready: %s\n", ppa_strerror(err));
ppa_context_unref(data->context);
data->context = NULL;
@@ -389,7 +498,6 @@ static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{
}
ppa_threaded_mainloop_wait(data->loop);
ppa_threaded_mainloop_accept(data->loop);
}
ppa_context_set_state_callback(data->context, context_state_callback2, device);
@@ -445,8 +553,7 @@ static ALCboolean pulse_open_playback(ALCdevice *device, const ALCchar *device_n
else if(strcmp(device_name, pulse_device) != 0)
return ALC_FALSE;
pulse_load();
if(!pa_handle)
if(!pulse_load())
return ALC_FALSE;
if(pulse_open(device, device_name) != ALC_FALSE)
@@ -465,11 +572,38 @@ static void pulse_close_playback(ALCdevice *device) //{{{
static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
pa_stream_flags_t flags = 0;
pa_stream_state_t state;
pa_channel_map chanmap;
ppa_threaded_mainloop_lock(data->loop);
if(!ConfigValueExists(NULL, "format"))
{
pa_operation *o;
struct {
pa_threaded_mainloop *loop;
char *name;
} server_data;
server_data.loop = data->loop;
server_data.name = NULL;
o = ppa_context_get_server_info(data->context, server_info_callback, &server_data);
while(ppa_operation_get_state(o) == PA_OPERATION_RUNNING)
ppa_threaded_mainloop_wait(data->loop);
ppa_operation_unref(o);
if(server_data.name)
{
o = ppa_context_get_sink_info_by_name(data->context, server_data.name, sink_info_callback, device);
while(ppa_operation_get_state(o) == PA_OPERATION_RUNNING)
ppa_threaded_mainloop_wait(data->loop);
ppa_operation_unref(o);
free(server_data.name);
}
}
if(!ConfigValueExists(NULL, "frequency"))
flags |= PA_STREAM_FIX_RATE;
data->frame_size = aluBytesFromFormat(device->Format) *
aluChannelsFromFormat(device->Format);
data->attr.minreq = data->frame_size * device->UpdateSize;
@@ -505,40 +639,13 @@ static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{
return ALC_FALSE;
}
#ifdef _WIN32
if(!ppa_channel_map_init_auto(&chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX))
{
AL_PRINT("Couldn't build map for channel count (%d)!", data->spec.channels);
AL_PRINT("Couldn't build map for channel count (%d)!\n", data->spec.channels);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
#else
switch(data->spec.channels)
{
case 1:
ppa_channel_map_parse(&chanmap, "mono");
break;
case 2:
ppa_channel_map_parse(&chanmap, "front-left,front-right");
break;
case 4:
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right");
break;
case 6:
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right,front-center,lfe");
break;
case 7:
ppa_channel_map_parse(&chanmap, "front-left,front-right,front-center,lfe,rear-center,side-left,side-right");
break;
case 8:
ppa_channel_map_parse(&chanmap, "front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right");
break;
default:
AL_PRINT("Got unhandled channel count (%d)!", data->spec.channels);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
}
#endif
SetDefaultWFXChannelOrder(device);
data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, &chanmap);
if(!data->stream)
@@ -551,9 +658,8 @@ static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{
}
ppa_stream_set_state_callback(data->stream, stream_state_callback, device);
ppa_stream_set_write_callback(data->stream, stream_write_callback, device);
if(ppa_stream_connect_playback(data->stream, NULL, &data->attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0)
if(ppa_stream_connect_playback(data->stream, NULL, &data->attr, flags, NULL, NULL) < 0)
{
AL_PRINT("Stream did not connect: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
@@ -580,12 +686,37 @@ static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{
}
ppa_threaded_mainloop_wait(data->loop);
ppa_threaded_mainloop_accept(data->loop);
}
ppa_stream_set_state_callback(data->stream, stream_state_callback2, device);
data->spec = *(ppa_stream_get_sample_spec(data->stream));
if(device->Frequency != data->spec.rate)
{
pa_operation *o;
/* Server updated our playback rate, so modify the buffer attribs
* accordingly. */
data->attr.minreq = (ALuint64)(data->attr.minreq/data->frame_size) *
data->spec.rate / device->Frequency * data->frame_size;
data->attr.tlength = data->attr.minreq * device->NumUpdates;
o = ppa_stream_set_buffer_attr(data->stream, &data->attr,
stream_success_callback, device);
while(ppa_operation_get_state(o) == PA_OPERATION_RUNNING)
ppa_threaded_mainloop_wait(data->loop);
ppa_operation_unref(o);
device->Frequency = data->spec.rate;
}
stream_buffer_attr_callback(data->stream, device);
ppa_stream_set_buffer_attr_callback(data->stream, stream_buffer_attr_callback, device);
#if PA_CHECK_VERSION(0,9,15)
if(ppa_stream_set_buffer_attr_callback)
ppa_stream_set_buffer_attr_callback(data->stream, stream_buffer_attr_callback, device);
#endif
stream_write_callback(data->stream, data->attr.tlength, device);
ppa_stream_set_write_callback(data->stream, stream_write_callback, device);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_TRUE;
@@ -611,15 +742,16 @@ static void pulse_stop_playback(ALCdevice *device) //{{{
static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_name) //{{{
{
pulse_data *data;
pa_stream_flags_t flags = 0;
pa_stream_state_t state;
pa_channel_map chanmap;
if(!device_name)
device_name = pulse_capture_device;
else if(strcmp(device_name, pulse_capture_device) != 0)
return ALC_FALSE;
pulse_load();
if(!pa_handle)
if(!pulse_load())
return ALC_FALSE;
if(pulse_open(device, device_name) == ALC_FALSE)
@@ -638,16 +770,15 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
if(!(data->ring = CreateRingBuffer(data->frame_size, data->samples)))
{
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
goto fail;
}
data->attr.minreq = -1;
data->attr.prebuf = -1;
data->attr.maxlength = -1;
data->attr.maxlength = data->frame_size * data->samples;
data->attr.tlength = -1;
data->attr.fragsize = data->frame_size * data->samples / 2;
data->attr.fragsize = min(data->frame_size * data->samples,
10 * device->Frequency / 1000);
data->stream_name = "Capture Stream";
data->spec.rate = device->Frequency;
@@ -667,46 +798,46 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
default:
AL_PRINT("Unknown format: 0x%x\n", device->Format);
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
goto fail;
}
if(ppa_sample_spec_valid(&data->spec) == 0)
{
AL_PRINT("Invalid sample format\n");
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
goto fail;
}
data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, NULL);
if(!ppa_channel_map_init_auto(&chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX))
{
AL_PRINT("Couldn't build map for channel count (%d)!\n", data->spec.channels);
ppa_threaded_mainloop_unlock(data->loop);
goto fail;
}
data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, &chanmap);
if(!data->stream)
{
AL_PRINT("pa_stream_new() failed: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_threaded_mainloop_unlock(data->loop);
pulse_close(device);
pulse_unload();
return ALC_FALSE;
goto fail;
}
ppa_stream_set_state_callback(data->stream, stream_state_callback, device);
if(ppa_stream_connect_record(data->stream, NULL, &data->attr, PA_STREAM_ADJUST_LATENCY) < 0)
flags |= PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY;
if(ppa_stream_connect_record(data->stream, NULL, &data->attr, flags) < 0)
{
AL_PRINT("Stream did not connect: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
ppa_stream_unref(data->stream);
ppa_threaded_mainloop_unlock(data->loop);
data->stream = NULL;
pulse_close(device);
pulse_unload();
return ALC_FALSE;
ppa_threaded_mainloop_unlock(data->loop);
goto fail;
}
while((state=ppa_stream_get_state(data->stream)) != PA_STREAM_READY)
@@ -717,21 +848,23 @@ static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_na
ppa_strerror(ppa_context_errno(data->context)));
ppa_stream_unref(data->stream);
ppa_threaded_mainloop_unlock(data->loop);
data->stream = NULL;
pulse_close(device);
pulse_unload();
return ALC_FALSE;
ppa_threaded_mainloop_unlock(data->loop);
goto fail;
}
ppa_threaded_mainloop_wait(data->loop);
ppa_threaded_mainloop_accept(data->loop);
}
ppa_stream_set_state_callback(data->stream, stream_state_callback2, device);
ppa_threaded_mainloop_unlock(data->loop);
return ALC_TRUE;
fail:
pulse_close(device);
pulse_unload();
return ALC_FALSE;
} //}}}
static void pulse_close_capture(ALCdevice *device) //{{{
@@ -743,18 +876,26 @@ static void pulse_close_capture(ALCdevice *device) //{{{
static void pulse_start_capture(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
pa_operation *o;
ppa_threaded_mainloop_lock(data->loop);
ppa_stream_set_read_callback(data->stream, stream_read_callback, device);
o = ppa_stream_cork(data->stream, 0, stream_success_callback, device);
while(ppa_operation_get_state(o) == PA_OPERATION_RUNNING)
ppa_threaded_mainloop_wait(data->loop);
ppa_operation_unref(o);
ppa_threaded_mainloop_unlock(data->loop);
} //}}}
static void pulse_stop_capture(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
pa_operation *o;
ppa_threaded_mainloop_lock(data->loop);
ppa_stream_set_read_callback(data->stream, NULL, NULL);
o = ppa_stream_cork(data->stream, 1, stream_success_callback, device);
while(ppa_operation_get_state(o) == PA_OPERATION_RUNNING)
ppa_threaded_mainloop_wait(data->loop);
ppa_operation_unref(o);
ppa_threaded_mainloop_unlock(data->loop);
} //}}}
@@ -762,17 +903,71 @@ static void pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint sa
{
pulse_data *data = device->ExtraData;
ALCuint available = RingBufferSize(data->ring);
const void *buf;
size_t length;
if(available < samples)
alcSetError(ALC_INVALID_VALUE);
else
ReadRingBuffer(data->ring, buffer, samples);
available *= data->frame_size;
samples *= data->frame_size;
ppa_threaded_mainloop_lock(data->loop);
if(available+ppa_stream_readable_size(data->stream) < samples)
{
ppa_threaded_mainloop_unlock(data->loop);
alcSetError(device, ALC_INVALID_VALUE);
return;
}
available = min(available, samples);
if(available > 0)
{
ReadRingBuffer(data->ring, buffer, available/data->frame_size);
buffer = (ALubyte*)buffer + available;
samples -= available;
}
/* Capture is done in fragment-sized chunks, so we loop until we get all
* that's requested */
while(samples > 0)
{
if(ppa_stream_peek(data->stream, &buf, &length) < 0)
{
AL_PRINT("pa_stream_peek() failed: %s\n",
ppa_strerror(ppa_context_errno(data->context)));
break;
}
available = min(length, samples);
memcpy(buffer, buf, available);
buffer = (ALubyte*)buffer + available;
buf = (const ALubyte*)buf + available;
samples -= available;
length -= available;
/* Any unread data in the fragment will be lost, so save it */
length /= data->frame_size;
if(length > 0)
{
if(length > data->samples)
length = data->samples;
WriteRingBuffer(data->ring, buf, length);
}
ppa_stream_drop(data->stream);
}
ppa_threaded_mainloop_unlock(data->loop);
} //}}}
static ALCuint pulse_available_samples(ALCdevice *device) //{{{
{
pulse_data *data = device->ExtraData;
return RingBufferSize(data->ring);
ALCuint ret;
ppa_threaded_mainloop_lock(data->loop);
ret = RingBufferSize(data->ring);
ret += ppa_stream_readable_size(data->stream)/data->frame_size;
ppa_threaded_mainloop_unlock(data->loop);
return ret;
} //}}}
BackendFuncs pulse_funcs = { //{{{
@@ -791,6 +986,10 @@ BackendFuncs pulse_funcs = { //{{{
void alc_pulse_init(BackendFuncs *func_list) //{{{
{
*func_list = pulse_funcs;
pulse_ctx_flags = 0;
if(!GetConfigValueBool("pulse", "spawn-server", 0))
pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN;
} //}}}
void alc_pulse_deinit(void) //{{{
@@ -799,8 +998,7 @@ void alc_pulse_deinit(void) //{{{
void alc_pulse_probe(int type) //{{{
{
pulse_load();
if(!pa_handle) return;
if(!pulse_load()) return;
if(type == DEVICE_PROBE)
AppendDeviceList(pulse_device);
+18 -5
View File
@@ -57,6 +57,8 @@ static ALuint SolarisProc(ALvoid *ptr)
ALint frameSize;
int wrote;
EnableRTPrio(RTPrioLevel);
frameSize = aluChannelsFromFormat(pDevice->Format) *
aluBytesFromFormat(pDevice->Format);
@@ -75,10 +77,10 @@ static ALuint SolarisProc(ALvoid *ptr)
{
AL_PRINT("write failed: %s\n", strerror(errno));
aluHandleDisconnect(pDevice);
len = 0;
break;
}
else
Sleep(1);
Sleep(1);
continue;
}
@@ -110,7 +112,8 @@ static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *device
if(data->fd == -1)
{
free(data);
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
if(errno != ENOENT)
AL_PRINT("Could not open %s: %s\n", driver, strerror(errno));
return ALC_FALSE;
}
@@ -195,6 +198,8 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
data->data_size = device->UpdateSize * frameSize;
data->mix_data = calloc(1, data->data_size);
SetDefaultChannelOrder(device);
data->thread = StartThread(SolarisProc, device);
if(data->thread == NULL)
{
@@ -217,6 +222,8 @@ static void solaris_stop_playback(ALCdevice *device)
StopThread(data->thread);
data->thread = NULL;
data->killNow = 0;
free(data->mix_data);
data->mix_data = NULL;
}
@@ -283,8 +290,14 @@ void alc_solaris_deinit(void)
{
}
void alc_solaris_probe(ALCboolean capture)
void alc_solaris_probe(int type)
{
#ifdef HAVE_STAT
struct stat buf;
if(stat(GetConfigValue("solaris", "device", "/dev/audio"), &buf) != 0)
return;
#endif
if(type == DEVICE_PROBE)
AppendDeviceList(solaris_device);
else if(type == ALL_DEVICE_PROBE)
+28 -48
View File
@@ -150,21 +150,25 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
bits = aluBytesFromFormat(device->Format) * 8;
channels = aluChannelsFromFormat(device->Format);
switch(bits)
{
case 8:
case 16:
case 32:
if(channels == 0)
{
AL_PRINT("Unknown format?! %x\n", device->Format);
return ALC_FALSE;
}
break;
default:
AL_PRINT("Unknown format?! %x\n", device->Format);
return ALC_FALSE;
if(channels != 1 && channels != 2)
{
if(bits == 8)
device->Format = AL_FORMAT_STEREO8;
else
{
device->Format = AL_FORMAT_STEREO16;
bits = 16;
}
channels = 2;
}
else if(bits != 8 && bits != 16)
{
if(channels == 1)
device->Format = AL_FORMAT_MONO16;
else
device->Format = AL_FORMAT_STEREO16;
bits = 16;
}
fprintf(data->f, "RIFF");
@@ -227,6 +231,8 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
return ALC_FALSE;
}
SetDefaultWFXChannelOrder(device);
data->thread = StartThread(WaveProc, device);
if(data->thread == NULL)
{
@@ -251,6 +257,8 @@ static void wave_stop_playback(ALCdevice *device)
StopThread(data->thread);
data->thread = NULL;
data->killNow = 0;
free(data->buffer);
data->buffer = NULL;
@@ -284,34 +292,6 @@ static ALCboolean wave_open_capture(ALCdevice *pDevice, const ALCchar *deviceNam
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,
@@ -319,11 +299,11 @@ BackendFuncs wave_funcs = {
wave_reset_playback,
wave_stop_playback,
wave_open_capture,
wave_close_capture,
wave_start_capture,
wave_stop_capture,
wave_capture_samples,
wave_available_samples
NULL,
NULL,
NULL,
NULL,
NULL
};
void alc_wave_init(BackendFuncs *func_list)
@@ -337,7 +317,7 @@ void alc_wave_deinit(void)
void alc_wave_probe(int type)
{
if(*(GetConfigValue("wave", "file", "")) == 0)
if(!ConfigValueExists("wave", "file"))
return;
if(type == DEVICE_PROBE)
+2 -2
View File
@@ -202,7 +202,7 @@ static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName
pData = calloc(1, sizeof(*pData));
if(!pData)
{
alcSetError(ALC_OUT_OF_MEMORY);
alcSetError(pDevice, ALC_OUT_OF_MEMORY);
return ALC_FALSE;
}
@@ -373,7 +373,7 @@ static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lS
frameSize;
if(ulSamples > ulCapturedSamples)
{
alcSetError(ALC_INVALID_VALUE);
alcSetError(pDevice, ALC_INVALID_VALUE);
return;
}
+13 -5
View File
@@ -6,6 +6,8 @@ IF(COMMAND CMAKE_POLICY)
CMAKE_POLICY(SET CMP0003 NEW)
ENDIF(COMMAND CMAKE_POLICY)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
INCLUDE(CheckFunctionExists)
INCLUDE(CheckLibraryExists)
INCLUDE(CheckIncludeFile)
@@ -47,8 +49,8 @@ ELSE()
ENDIF()
SET(LIB_MAJOR_VERSION "1")
SET(LIB_MINOR_VERSION "10")
SET(LIB_BUILD_VERSION "622")
SET(LIB_MINOR_VERSION "11")
SET(LIB_BUILD_VERSION "753")
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
IF(NOT DEFINED LIB_INSTALL_DIR)
SET(LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
@@ -134,6 +136,9 @@ ELSE()
ENDIF()
ENDIF()
CHECK_C_SOURCE_COMPILES("int foo(const char *str, ...) __attribute__((format(printf, 1, 2)));
int main() {return 0;}" HAVE_GCC_FORMAT)
CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H)
CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H)
@@ -150,6 +155,7 @@ ENDIF()
CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
CHECK_FUNCTION_EXISTS(_controlfp HAVE__CONTROLFP)
CHECK_FUNCTION_EXISTS(stat HAVE_STAT)
CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
IF(NOT HAVE_STRCASECMP)
CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
@@ -247,6 +253,8 @@ IF(NOT HAVE_WINDOWS_H)
SET(EXTRA_LIBS pthread ${EXTRA_LIBS})
ENDIF()
CHECK_LIBRARY_EXISTS(pthread pthread_setschedparam "" HAVE_PTHREAD_SETSCHEDPARAM)
CHECK_LIBRARY_EXISTS(rt clock_gettime "" HAVE_LIBRT)
IF(HAVE_LIBRT)
SET(EXTRA_LIBS rt ${EXTRA_LIBS})
@@ -424,8 +432,8 @@ CONFIGURE_FILE(
"${OpenAL_SOURCE_DIR}/config.h.in"
"${OpenAL_BINARY_DIR}/config.h")
CONFIGURE_FILE(
"${OpenAL_SOURCE_DIR}/admin/pkgconfig/openal.pc.in"
"${OpenAL_BINARY_DIR}/admin/pkgconfig/openal.pc"
"${OpenAL_SOURCE_DIR}/openal.pc.in"
"${OpenAL_BINARY_DIR}/openal.pc"
@ONLY)
ADD_DEFINITIONS(-DAL_BUILD_LIBRARY)
@@ -454,7 +462,7 @@ INSTALL(FILES include/AL/al.h
include/AL/alext.h
DESTINATION include/AL
)
INSTALL(FILES "${OpenAL_BINARY_DIR}/admin/pkgconfig/openal.pc"
INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc"
DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
# Install alsoft.conf configuration file
+1 -1
View File
@@ -11,7 +11,7 @@ extern "C" {
typedef struct ALbuffer
{
ALshort *data;
ALfloat *data;
ALsizei size;
ALenum format;
+28
View File
@@ -49,6 +49,34 @@ static __inline ALfloat lpFilter2P(FILTER *iir, ALuint offset, ALfloat input)
return output;
}
static __inline ALfloat lpFilter1P(FILTER *iir, ALuint offset, ALfloat input)
{
ALfloat *history = &iir->history[offset];
ALfloat a = iir->coeff;
ALfloat output = input;
output = output + (history[0]-output)*a;
history[0] = output;
return output;
}
/* Calculates the low-pass filter coefficient given the pre-scaled gain and
* cos(w) value. Note that g should be pre-scaled (sqr(gain) for one-pole,
* sqrt(gain) for four-pole, etc) */
static __inline ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
{
ALfloat a = 0.0f;
/* Be careful with gains < 0.01, as that causes the coefficient
* head towards 1, which will flatten the signal */
g = __max(g, 0.01f);
if(g < 0.9999f) /* 1-epsilon */
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
(1 - g);
return a;
}
#define AL_FILTER_TYPE 0x8001
+66 -31
View File
@@ -13,6 +13,27 @@
#include "AL/alc.h"
#include "AL/alext.h"
#if defined(HAVE_STDINT_H)
#include <stdint.h>
typedef int64_t ALint64;
typedef uint64_t ALuint64;
#elif defined(HAVE___INT64)
typedef __int64 ALint64;
typedef unsigned __int64 ALuint64;
#elif (SIZEOF_LONG == 8)
typedef long ALint64;
typedef unsigned long ALuint64;
#elif (SIZEOF_LONG_LONG == 8)
typedef long long ALint64;
typedef unsigned long long ALuint64;
#endif
#ifdef HAVE_GCC_FORMAT
#define PRINTF_STYLE(x, y) __attribute__((format(printf, (x), (y))))
#else
#define PRINTF_STYLE(x, y)
#endif
#ifdef _WIN32
#ifndef _WIN32_WINNT
@@ -38,7 +59,7 @@ typedef DWORD tls_type;
#include <time.h>
#include <errno.h>
#define IsBadWritePtr(a,b) (0)
#define IsBadWritePtr(a,b) ((a) == NULL && (b) != 0)
typedef pthread_key_t tls_type;
#define tls_create(x) pthread_key_create((x), NULL)
@@ -130,31 +151,6 @@ static inline void Sleep(ALuint t)
extern "C" {
#endif
static __inline void al_print(const char *fname, unsigned int line, const char *fmt, ...)
{
const char *fn;
char str[256];
int i;
fn = strrchr(fname, '/');
if(!fn) fn = strrchr(fname, '\\');;
if(!fn) fn = fname;
else fn += 1;
i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line);
if(i < (int)sizeof(str) && i > 0)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(str+i, sizeof(str)-i, fmt, ap);
va_end(ap);
}
str[sizeof(str)-1] = 0;
fprintf(stderr, "%s", str);
}
#define AL_PRINT(...) al_print(__FILE__, __LINE__, __VA_ARGS__)
#define SWMIXER_OUTPUT_RATE 44100
@@ -163,8 +159,25 @@ static __inline void al_print(const char *fname, unsigned int line, const char *
#define LOWPASSFREQCUTOFF (5000)
#define QUADRANT_NUM 128
#define LUT_NUM (4 * QUADRANT_NUM)
#define DEFAULT_HEAD_DAMPEN (0.25f)
// Find the next power-of-2 for non-power-of-2 numbers.
static __inline ALuint NextPowerOf2(ALuint value)
{
ALuint powerOf2 = 1;
if(value)
{
value--;
while(value)
{
value >>= 1;
powerOf2 <<= 1;
}
}
return powerOf2;
}
typedef struct {
@@ -195,7 +208,7 @@ void alc_oss_deinit(void);
void alc_oss_probe(int type);
void alc_solaris_init(BackendFuncs *func_list);
void alc_solaris_deinit(void);
void alc_solarise_probe(int type);
void alc_solaris_probe(int type);
void alcDSoundInit(BackendFuncs *func_list);
void alcDSoundDeinit(void);
void alcDSoundProbe(int type);
@@ -225,6 +238,8 @@ struct ALCdevice_struct
ALCchar *szDeviceName;
ALCenum LastError;
// Maximum number of sources that can be created
ALuint MaxNoOfSources;
// Maximum number of slots that can be created
@@ -254,9 +269,14 @@ struct ALCdevice_struct
struct bs2b *Bs2b;
ALCint Bs2bLevel;
// Simulated dampening from head occlusion
ALfloat HeadDampen;
// Dry path buffer mix
float DryBuffer[BUFFERSIZE][OUTPUTCHANNELS];
Channel DevChannels[OUTPUTCHANNELS];
// Contexts created on this device
ALCcontext **Contexts;
ALuint NumContexts;
@@ -294,7 +314,10 @@ struct ALCcontext_struct
ALenum LastError;
ALboolean InUse;
ALboolean Suspended;
ALenum DistanceModel;
ALboolean SourceDistanceModel;
ALfloat DopplerFactor;
ALfloat DopplerVelocity;
@@ -311,13 +334,15 @@ struct ALCcontext_struct
ALCcontext *next;
};
extern ALint RTPrioLevel;
ALCvoid ReleaseALC(ALCvoid);
void AppendDeviceList(const ALCchar *name);
void AppendAllDeviceList(const ALCchar *name);
void AppendCaptureDeviceList(const ALCchar *name);
ALCvoid alcSetError(ALenum errorCode);
ALCvoid alcSetError(ALCdevice *device, ALenum errorCode);
ALCvoid SuspendContext(ALCcontext *context);
ALCvoid ProcessContext(ALCcontext *context);
@@ -336,10 +361,20 @@ void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len);
void ReadALConfig(void);
void FreeALConfig(void);
int ConfigValueExists(const char *blockName, const char *keyName);
const char *GetConfigValue(const char *blockName, const char *keyName, const char *def);
int GetConfigValueInt(const char *blockName, const char *keyName, int def);
float GetConfigValueFloat(const char *blockName, const char *keyName, float def);
int GetConfigValueBool(const char *blockName, const char *keyName, float def);
int GetConfigValueBool(const char *blockName, const char *keyName, int def);
void EnableRTPrio(ALint level);
void SetDefaultChannelOrder(ALCdevice *device);
void SetDefaultWFXChannelOrder(ALCdevice *device);
void al_print(const char *fname, unsigned int line, const char *fmt, ...)
PRINTF_STYLE(3,4);
#define AL_PRINT(...) al_print(__FILE__, __LINE__, __VA_ARGS__)
ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context);
ALCcontext* ALCAPIENTRY alcGetThreadContext(void);
+15 -1
View File
@@ -22,6 +22,17 @@
extern "C" {
#endif
typedef enum {
POINT_RESAMPLER = 0,
LINEAR_RESAMPLER,
COSINE_RESAMPLER,
RESAMPLER_MAX,
RESAMPLER_MIN = -1,
RESAMPLER_DEFAULT = LINEAR_RESAMPLER
} resampler_t;
extern resampler_t DefaultResampler;
typedef struct ALbufferlistitem
{
struct ALbuffer *buffer;
@@ -47,6 +58,8 @@ typedef struct ALsource
ALboolean bLooping;
ALenum DistanceModel;
resampler_t Resampler;
ALenum state;
ALuint position;
ALuint position_fraction;
@@ -85,6 +98,7 @@ typedef struct ALsource
ALboolean FirstStart;
// Current target parameters used for mixing
ALboolean NeedsUpdate;
struct {
ALfloat DryGains[OUTPUTCHANNELS];
ALfloat WetGains[MAX_SENDS];
@@ -92,7 +106,7 @@ typedef struct ALsource
struct {
FILTER iirFilter;
ALfloat history[2];
ALfloat history[OUTPUTCHANNELS];
} Send[MAX_SENDS];
FILTER iirFilter;
+23 -5
View File
@@ -5,6 +5,7 @@
#include "AL/alc.h"
#include "AL/alext.h"
#include <math.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
@@ -46,23 +47,26 @@
#define __min min
#endif
#define QUADRANT_NUM 128
#define LUT_NUM (4 * QUADRANT_NUM)
#ifdef __cplusplus
extern "C" {
#endif
enum {
typedef enum {
FRONT_LEFT = 0,
FRONT_RIGHT,
FRONT_CENTER,
SIDE_LEFT,
SIDE_RIGHT,
LFE,
BACK_LEFT,
BACK_RIGHT,
BACK_CENTER,
LFE,
SIDE_LEFT,
SIDE_RIGHT,
OUTPUTCHANNELS
};
} Channel;
#define BUFFERSIZE 24000
@@ -145,6 +149,20 @@ static __inline ALuint aluChannelsFromFormat(ALenum format)
}
}
static __inline ALint aluCart2LUTpos(ALfloat re, ALfloat im)
{
ALint pos = 0;
ALfloat denom = aluFabs(re) + aluFabs(im);
if(denom > 0.0f)
pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5);
if(re < 0.0)
pos = 2 * QUADRANT_NUM - pos;
if(im < 0.0)
pos = LUT_NUM - pos;
return pos%LUT_NUM;
}
ALvoid aluInitPanning(ALCcontext *Context);
ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
ALvoid aluHandleDisconnect(ALCdevice *device);
+28 -4
View File
@@ -29,6 +29,7 @@
#include "alAuxEffectSlot.h"
#include "alThunk.h"
#include "alError.h"
#include "alSource.h"
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
@@ -179,6 +180,7 @@ ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context = GetContextSuspended();
if(!Context) return;
@@ -194,6 +196,7 @@ ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint
{
ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
InitializeEffect(Context, ALEffectSlot, effect);
updateSources = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
@@ -201,7 +204,10 @@ ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint
case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
if(iValue == AL_TRUE || iValue == AL_FALSE)
{
ALEffectSlot->AuxSendAuto = iValue;
updateSources = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
@@ -214,6 +220,26 @@ ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint
else
alSetError(AL_INVALID_NAME);
// Force updating the sources that use this slot, since it affects the
// sending parameters
if(updateSources)
{
ALsource *source = Context->Source;
while(source)
{
ALuint i;
for(i = 0;i < MAX_SENDS;i++)
{
if(!source->Send[i].Slot ||
source->Send[i].Slot->effectslot != effectslot)
continue;
source->NeedsUpdate = AL_TRUE;
break;
}
source = source->next;
}
}
ProcessContext(Context);
}
@@ -482,11 +508,9 @@ static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot,
ALEffectSlot->EffectState = NewState;
}
if(!effect)
{
memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
return;
}
memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
else
memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
}
+61 -64
View File
@@ -33,9 +33,9 @@
static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat);
static void ConvertData(ALshort *dst, const ALvoid *src, ALint origBytes, ALsizei len);
static void ConvertDataRear(ALshort *dst, const ALvoid *src, ALint origBytes, ALsizei len);
static void ConvertDataIMA4(ALshort *dst, const ALvoid *src, ALint origChans, ALsizei len);
static void ConvertData(ALfloat *dst, const ALvoid *src, ALint origBytes, ALsizei len);
static void ConvertDataRear(ALfloat *dst, const ALvoid *src, ALint origBytes, ALsizei len);
static void ConvertDataIMA4(ALfloat *dst, const ALvoid *src, ALint origChans, ALsizei len);
/*
* AL Buffer Functions
@@ -122,8 +122,6 @@ ALAPI ALvoid ALAPIENTRY alGenBuffers(ALsizei n,ALuint *puiBuffers)
}
ProcessContext(Context);
return;
}
/*
@@ -204,9 +202,6 @@ ALAPI ALvoid ALAPIENTRY alDeleteBuffers(ALsizei n, const ALuint *puiBuffers)
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
return;
}
/*
@@ -294,20 +289,21 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
case AL_FORMAT_MONO8:
case AL_FORMAT_MONO16:
case AL_FORMAT_MONO_FLOAT32:
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO16);
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_MONO_FLOAT32);
break;
case AL_FORMAT_STEREO8:
case AL_FORMAT_STEREO16:
case AL_FORMAT_STEREO_FLOAT32:
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO16);
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_STEREO_FLOAT32);
break;
case AL_FORMAT_REAR8:
case AL_FORMAT_REAR16:
case AL_FORMAT_REAR32: {
ALuint NewFormat = AL_FORMAT_QUAD16;
ALuint NewFormat = AL_FORMAT_QUAD32;
ALuint NewChannels = aluChannelsFromFormat(NewFormat);
ALuint NewBytes = aluBytesFromFormat(NewFormat);
ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 :
((format==AL_FORMAT_REAR16) ? 2 :
4));
@@ -323,18 +319,16 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
size /= OrigBytes;
size *= 2;
// Samples are converted to 16 bit here
temp = realloc(ALBuf->data, (BUFFER_PADDING*NewChannels + size) * sizeof(ALshort));
// Samples are converted here
temp = realloc(ALBuf->data, (BUFFER_PADDING*NewChannels + size) * NewBytes);
if(temp)
{
ALBuf->data = temp;
ConvertDataRear(ALBuf->data, data, OrigBytes, size);
memset(&(ALBuf->data[size]), 0, BUFFER_PADDING*NewChannels*sizeof(ALshort));
ALBuf->format = NewFormat;
ALBuf->eOriginalFormat = format;
ALBuf->size = size*sizeof(ALshort);
ALBuf->size = size*NewBytes;
ALBuf->frequency = freq;
}
else
@@ -346,30 +340,33 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
case AL_FORMAT_QUAD8:
case AL_FORMAT_QUAD16:
case AL_FORMAT_QUAD32:
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_QUAD16);
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_QUAD32);
break;
case AL_FORMAT_51CHN8:
case AL_FORMAT_51CHN16:
case AL_FORMAT_51CHN32:
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_51CHN16);
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_51CHN32);
break;
case AL_FORMAT_61CHN8:
case AL_FORMAT_61CHN16:
case AL_FORMAT_61CHN32:
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_61CHN16);
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_61CHN32);
break;
case AL_FORMAT_71CHN8:
case AL_FORMAT_71CHN16:
case AL_FORMAT_71CHN32:
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_71CHN16);
LoadData(ALBuf, data, size, freq, format, AL_FORMAT_71CHN32);
break;
case AL_FORMAT_MONO_IMA4:
case AL_FORMAT_STEREO_IMA4: {
int OrigChans = ((format==AL_FORMAT_MONO_IMA4) ? 1 : 2);
ALuint NewFormat = ((OrigChans==1) ? AL_FORMAT_MONO_FLOAT32 :
AL_FORMAT_STEREO_FLOAT32);
ALuint NewBytes = aluBytesFromFormat(NewFormat);
// Here is where things vary:
// nVidia and Apple use 64+1 samples per channel per block => block_size=36*chans bytes
@@ -384,17 +381,15 @@ ALAPI ALvoid ALAPIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *d
size *= 65;
// Allocate extra padding samples
temp = realloc(ALBuf->data, (BUFFER_PADDING*OrigChans + size)*sizeof(ALshort));
temp = realloc(ALBuf->data, (BUFFER_PADDING*OrigChans + size)*NewBytes);
if(temp)
{
ALBuf->data = temp;
ConvertDataIMA4(ALBuf->data, data, OrigChans, size/65);
memset(&(ALBuf->data[size]), 0, BUFFER_PADDING*sizeof(ALshort)*OrigChans);
ALBuf->format = ((OrigChans==1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16);
ALBuf->format = NewFormat;
ALBuf->eOriginalFormat = format;
ALBuf->size = size*sizeof(ALshort);
ALBuf->size = size*NewBytes;
ALBuf->frequency = freq;
}
else
@@ -473,6 +468,7 @@ ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *d
ALuint OrigBytes = ((format==AL_FORMAT_REAR8) ? 1 :
((format==AL_FORMAT_REAR16) ? 2 :
4));
ALuint NewBytes = aluBytesFromFormat(ALBuf->format);
if(ALBuf->eOriginalFormat != AL_FORMAT_REAR8 &&
ALBuf->eOriginalFormat != AL_FORMAT_REAR16 &&
@@ -482,7 +478,7 @@ ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *d
break;
}
if(ALBuf->size/4/sizeof(ALshort) < (ALuint)offset+length)
if(ALBuf->size/4/NewBytes < (ALuint)offset+length)
{
alSetError(AL_INVALID_VALUE);
break;
@@ -494,6 +490,7 @@ ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *d
case AL_FORMAT_MONO_IMA4:
case AL_FORMAT_STEREO_IMA4: {
int Channels = aluChannelsFromFormat(ALBuf->format);
ALuint Bytes = aluBytesFromFormat(ALBuf->format);
if(ALBuf->eOriginalFormat != format)
{
@@ -502,7 +499,7 @@ ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *d
}
if((offset%65) != 0 || (length%65) != 0 ||
ALBuf->size/Channels/sizeof(ALshort) < (ALuint)offset+length)
ALBuf->size/Channels/Bytes < (ALuint)offset+length)
{
alSetError(AL_INVALID_VALUE);
break;
@@ -514,6 +511,7 @@ ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *d
default: {
ALuint Channels = aluChannelsFromFormat(format);
ALuint Bytes = aluBytesFromFormat(format);
ALuint NewBytes = aluBytesFromFormat(ALBuf->format);
if(Channels != aluChannelsFromFormat(ALBuf->format))
{
@@ -521,7 +519,7 @@ ALvoid ALAPIENTRY alBufferSubDataEXT(ALuint buffer,ALenum format,const ALvoid *d
break;
}
if(ALBuf->size/Channels/sizeof(ALshort) < (ALuint)offset+length)
if(ALBuf->size/Channels/NewBytes < (ALuint)offset+length)
{
alSetError(AL_INVALID_VALUE);
break;
@@ -929,18 +927,19 @@ ALAPI void ALAPIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValue
* LoadData
*
* Loads the specified data into the buffer, using the specified formats.
* Currently, the new format must be 16-bit, and must have the same channel
* configuration as the original format. This does NOT handle compressed
* formats (eg. IMA4).
* Currently, the new format must be 32-bit float, and must have the same
* channel configuration as the original format. This does NOT handle
* compressed formats (eg. IMA4).
*/
static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint freq, ALenum OrigFormat, ALenum NewFormat)
{
ALuint NewBytes = aluBytesFromFormat(NewFormat);
ALuint NewChannels = aluChannelsFromFormat(NewFormat);
ALuint OrigBytes = aluBytesFromFormat(OrigFormat);
ALuint OrigChannels = aluChannelsFromFormat(OrigFormat);
ALvoid *temp;
assert(aluBytesFromFormat(NewFormat) == 2);
assert(NewBytes == 4);
assert(NewChannels == OrigChannels);
if ((size%(OrigBytes*OrigChannels)) != 0)
@@ -949,48 +948,48 @@ static void LoadData(ALbuffer *ALBuf, const ALubyte *data, ALsizei size, ALuint
return;
}
// Samples are converted to 16 bit here
// Samples are converted here
size /= OrigBytes;
temp = realloc(ALBuf->data, (BUFFER_PADDING*NewChannels + size) * sizeof(ALshort));
temp = realloc(ALBuf->data, (BUFFER_PADDING*NewChannels + size) * NewBytes);
if(temp)
{
ALBuf->data = temp;
ConvertData(ALBuf->data, data, OrigBytes, size);
memset(&(ALBuf->data[size]), 0, BUFFER_PADDING*NewChannels*sizeof(ALshort));
ALBuf->format = NewFormat;
ALBuf->eOriginalFormat = OrigFormat;
ALBuf->size = size*sizeof(ALshort);
ALBuf->size = size*NewBytes;
ALBuf->frequency = freq;
}
else
alSetError(AL_OUT_OF_MEMORY);
}
static void ConvertData(ALshort *dst, const ALvoid *src, ALint origBytes, ALsizei len)
static void ConvertData(ALfloat *dst, const ALvoid *src, ALint origBytes, ALsizei len)
{
ALsizei i;
ALint smp;
switch(origBytes)
{
case 1:
for(i = 0;i < len;i++)
dst[i] = ((ALshort)((ALubyte*)src)[i] - 128) << 8;
{
smp = ((ALubyte*)src)[i];
dst[i] = ((smp < 0x80) ? ((smp-128)/128.0f) : ((smp-128)/127.0f));
}
break;
case 2:
memcpy(dst, src, len*sizeof(ALshort));
for(i = 0;i < len;i++)
{
smp = ((ALshort*)src)[i];
dst[i] = ((smp < 0) ? (smp/32768.0f) : (smp/32767.0f));
}
break;
case 4:
for(i = 0;i < len;i++)
{
ALint smp;
smp = (((ALfloat*)src)[i] * 32767.5f - 0.5f);
smp = min(smp, 32767);
smp = max(smp, -32768);
dst[i] = (ALshort)smp;
}
dst[i] = ((ALfloat*)src)[i];
break;
default:
@@ -998,9 +997,10 @@ static void ConvertData(ALshort *dst, const ALvoid *src, ALint origBytes, ALsize
}
}
static void ConvertDataRear(ALshort *dst, const ALvoid *src, ALint origBytes, ALsizei len)
static void ConvertDataRear(ALfloat *dst, const ALvoid *src, ALint origBytes, ALsizei len)
{
ALsizei i;
ALint smp;
switch(origBytes)
{
case 1:
@@ -1008,8 +1008,10 @@ static void ConvertDataRear(ALshort *dst, const ALvoid *src, ALint origBytes, AL
{
dst[i+0] = 0;
dst[i+1] = 0;
dst[i+2] = ((ALshort)((ALubyte*)src)[i/2+0] - 128) << 8;
dst[i+3] = ((ALshort)((ALubyte*)src)[i/2+1] - 128) << 8;
smp = ((ALubyte*)src)[i/2+0];
dst[i+2] = ((smp < 0x80) ? ((smp-128)/128.0f) : ((smp-128)/127.0f));
smp = ((ALubyte*)src)[i/2+1];
dst[i+3] = ((smp < 0x80) ? ((smp-128)/128.0f) : ((smp-128)/127.0f));
}
break;
@@ -1018,25 +1020,20 @@ static void ConvertDataRear(ALshort *dst, const ALvoid *src, ALint origBytes, AL
{
dst[i+0] = 0;
dst[i+1] = 0;
dst[i+2] = ((ALshort*)src)[i/2+0];
dst[i+3] = ((ALshort*)src)[i/2+1];
smp = ((ALshort*)src)[i/2+0];
dst[i+2] = ((smp < 0) ? (smp/32768.0f) : (smp/32767.0f));
smp = ((ALshort*)src)[i/2+1];
dst[i+3] = ((smp < 0) ? (smp/32768.0f) : (smp/32767.0f));
}
break;
case 4:
for(i = 0;i < len;i+=4)
{
ALint smp;
dst[i+0] = 0;
dst[i+1] = 0;
smp = (((ALfloat*)src)[i/2+0] * 32767.5f - 0.5);
smp = min(smp, 32767);
smp = max(smp, -32768);
dst[i+2] = (ALshort)smp;
smp = (((ALfloat*)src)[i/2+1] * 32767.5f - 0.5);
smp = min(smp, 32767);
smp = max(smp, -32768);
dst[i+3] = (ALshort)smp;
dst[i+2] = ((ALfloat*)src)[i/2+0];
dst[i+3] = ((ALfloat*)src)[i/2+1];
}
break;
@@ -1045,7 +1042,7 @@ static void ConvertDataRear(ALshort *dst, const ALvoid *src, ALint origBytes, AL
}
}
static void ConvertDataIMA4(ALshort *dst, const ALvoid *src, ALint origChans, ALsizei len)
static void ConvertDataIMA4(ALfloat *dst, const ALvoid *src, ALint origChans, ALsizei len)
{
const ALuint *IMAData;
ALint Sample[2],Index[2];
@@ -1065,7 +1062,7 @@ static void ConvertDataIMA4(ALshort *dst, const ALvoid *src, ALint origChans, AL
Index[c] = ((Index[c]<0) ? 0 : Index[c]);
Index[c] = ((Index[c]>88) ? 88 : Index[c]);
dst[i*65*origChans + c] = (ALshort)Sample[c];
dst[i*65*origChans + c] = ((Sample[c] < 0) ? (Sample[c]/32768.0f) : (Sample[c]/32767.0f));
IMAData++;
}
@@ -1088,7 +1085,7 @@ static void ConvertDataIMA4(ALshort *dst, const ALvoid *src, ALint origChans, AL
if(Index[c]<0) Index[c] = 0;
else if(Index[c]>88) Index[c] = 88;
dst[(i*65+j+k)*origChans + c] = (ALshort)Sample[c];
dst[(i*65+j+k)*origChans + c] = ((Sample[c] < 0) ? (Sample[c]/32768.0f) : (Sample[c]/32767.0f));
IMACode[c] >>= 4;
}
}
+1 -4
View File
@@ -170,9 +170,6 @@ ALvoid ALAPIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers)
alSetError(AL_INVALID_VALUE);
ProcessContext(Context);
return;
}
/*
@@ -505,7 +502,7 @@ ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plVa
switch (eParam)
{
case AL_SIZE:
alGetBufferi(buffer, eParam, plValues);
alGetDatabufferiEXT(buffer, eParam, plValues);
break;
default:
+49 -18
View File
@@ -24,10 +24,12 @@
#include "AL/alc.h"
#include "alError.h"
#include "alListener.h"
#include "alSource.h"
ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
{
ALCcontext *pContext;
ALboolean updateAll = AL_FALSE;
pContext = GetContextSuspended();
if(!pContext) return;
@@ -36,14 +38,20 @@ ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
{
case AL_GAIN:
if(flValue >= 0.0f)
{
pContext->Listener.Gain = flValue;
updateAll = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_METERS_PER_UNIT:
if(flValue > 0.0f)
{
pContext->Listener.MetersPerUnit = flValue;
updateAll = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
@@ -53,6 +61,18 @@ ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
break;
}
// Force updating the sources for these parameters, since even head-
// relative sources are affected
if(updateAll)
{
ALsource *source = pContext->Source;
while(source)
{
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(pContext);
}
@@ -60,6 +80,7 @@ ALAPI ALvoid ALAPIENTRY alListenerf(ALenum eParam, ALfloat flValue)
ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3)
{
ALCcontext *pContext;
ALboolean updateWorld = AL_FALSE;
pContext = GetContextSuspended();
if(!pContext) return;
@@ -70,12 +91,14 @@ ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat fl
pContext->Listener.Position[0] = flValue1;
pContext->Listener.Position[1] = flValue2;
pContext->Listener.Position[2] = flValue3;
updateWorld = AL_TRUE;
break;
case AL_VELOCITY:
pContext->Listener.Velocity[0] = flValue1;
pContext->Listener.Velocity[1] = flValue2;
pContext->Listener.Velocity[2] = flValue3;
updateWorld = AL_TRUE;
break;
default:
@@ -83,6 +106,17 @@ ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat fl
break;
}
if(updateWorld)
{
ALsource *source = pContext->Source;
while(source)
{
if(!source->bHeadRelative)
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(pContext);
}
@@ -90,6 +124,7 @@ ALAPI ALvoid ALAPIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat fl
ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
{
ALCcontext *pContext;
ALboolean updateWorld = AL_FALSE;
pContext = GetContextSuspended();
if(!pContext) return;
@@ -99,29 +134,13 @@ ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
switch(eParam)
{
case AL_GAIN:
if(pflValues[0] >= 0.0f)
pContext->Listener.Gain = pflValues[0];
else
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);
alListenerf(eParam, pflValues[0]);
break;
case AL_POSITION:
pContext->Listener.Position[0] = pflValues[0];
pContext->Listener.Position[1] = pflValues[1];
pContext->Listener.Position[2] = pflValues[2];
break;
case AL_VELOCITY:
pContext->Listener.Velocity[0] = pflValues[0];
pContext->Listener.Velocity[1] = pflValues[1];
pContext->Listener.Velocity[2] = pflValues[2];
alListener3f(eParam, pflValues[0], pflValues[1], pflValues[2]);
break;
case AL_ORIENTATION:
@@ -132,6 +151,7 @@ ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
pContext->Listener.Up[0] = pflValues[3];
pContext->Listener.Up[1] = pflValues[4];
pContext->Listener.Up[2] = pflValues[5];
updateWorld = AL_TRUE;
break;
default:
@@ -142,6 +162,17 @@ ALAPI ALvoid ALAPIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues)
else
alSetError(AL_INVALID_VALUE);
if(updateWorld)
{
ALsource *source = pContext->Source;
while(source)
{
if(!source->bHeadRelative)
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(pContext);
}
+176 -101
View File
@@ -32,9 +32,9 @@
#include "alThunk.h"
#include "alAuxEffectSlot.h"
static ALvoid InitSourceParams(ALCcontext *Context, ALsource *pSource);
static ALvoid InitSourceParams(ALsource *pSource);
static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset, ALuint updateSize);
static ALvoid ApplyOffset(ALsource *pSource, ALboolean bUpdateContext);
static ALboolean ApplyOffset(ALsource *pSource);
static ALint GetByteOffset(ALsource *pSource);
ALAPI ALvoid ALAPIENTRY alGenSources(ALsizei n,ALuint *sources)
@@ -74,7 +74,7 @@ ALAPI ALvoid ALAPIENTRY alGenSources(ALsizei n,ALuint *sources)
sources[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
(*list)->source = sources[i];
InitSourceParams(Context, *list);
InitSourceParams(*list);
Context->SourceCount++;
i++;
@@ -230,6 +230,7 @@ ALAPI ALvoid ALAPIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
pSource->flPitch = flValue;
if(pSource->flPitch < 0.001f)
pSource->flPitch = 0.001f;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
@@ -237,91 +238,130 @@ ALAPI ALvoid ALAPIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
case AL_CONE_INNER_ANGLE:
if(flValue >= 0.0f && flValue <= 360.0f)
{
pSource->flInnerAngle = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_CONE_OUTER_ANGLE:
if(flValue >= 0.0f && flValue <= 360.0f)
{
pSource->flOuterAngle = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_GAIN:
if(flValue >= 0.0f)
{
pSource->flGain = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_MAX_DISTANCE:
if(flValue >= 0.0f)
{
pSource->flMaxDistance = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_ROLLOFF_FACTOR:
if(flValue >= 0.0f)
{
pSource->flRollOffFactor = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_REFERENCE_DISTANCE:
if(flValue >= 0.0f)
{
pSource->flRefDistance = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_MIN_GAIN:
if(flValue >= 0.0f && flValue <= 1.0f)
{
pSource->flMinGain = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_MAX_GAIN:
if(flValue >= 0.0f && flValue <= 1.0f)
{
pSource->flMaxGain = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_CONE_OUTER_GAIN:
if(flValue >= 0.0f && flValue <= 1.0f)
{
pSource->flOuterGain = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_CONE_OUTER_GAINHF:
if(flValue >= 0.0f && flValue <= 1.0f)
{
pSource->OuterGainHF = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_AIR_ABSORPTION_FACTOR:
if(flValue >= 0.0f && flValue <= 10.0f)
{
pSource->AirAbsorptionFactor = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_ROOM_ROLLOFF_FACTOR:
if(flValue >= 0.0f && flValue <= 10.0f)
{
pSource->RoomRolloffFactor = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_DOPPLER_FACTOR:
if(flValue >= 0.0f && flValue <= 1.0f)
{
pSource->DopplerFactor = flValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
@@ -340,7 +380,10 @@ ALAPI ALvoid ALAPIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
pSource->lOffset = (ALint)flValue;
if ((pSource->state == AL_PLAYING) || (pSource->state == AL_PAUSED))
ApplyOffset(pSource, AL_TRUE);
{
if(ApplyOffset(pSource) == AL_FALSE)
alSetError(AL_INVALID_VALUE);
}
}
else
alSetError(AL_INVALID_VALUE);
@@ -378,18 +421,21 @@ ALAPI ALvoid ALAPIENTRY alSource3f(ALuint source, ALenum eParam, ALfloat flValue
pSource->vPosition[0] = flValue1;
pSource->vPosition[1] = flValue2;
pSource->vPosition[2] = flValue3;
pSource->NeedsUpdate = AL_TRUE;
break;
case AL_VELOCITY:
pSource->vVelocity[0] = flValue1;
pSource->vVelocity[1] = flValue2;
pSource->vVelocity[2] = flValue3;
pSource->NeedsUpdate = AL_TRUE;
break;
case AL_DIRECTION:
pSource->vOrientation[0] = flValue1;
pSource->vOrientation[1] = flValue2;
pSource->vOrientation[2] = flValue3;
pSource->NeedsUpdate = AL_TRUE;
break;
default:
@@ -480,21 +526,30 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
case AL_SOURCE_RELATIVE:
if(lValue == AL_FALSE || lValue == AL_TRUE)
{
pSource->bHeadRelative = (ALboolean)lValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_CONE_INNER_ANGLE:
if(lValue >= 0 && lValue <= 360)
{
pSource->flInnerAngle = (float)lValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_CONE_OUTER_ANGLE:
if(lValue >= 0 && lValue <= 360)
{
pSource->flOuterAngle = (float)lValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
@@ -555,6 +610,7 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
// Update AL_BUFFER parameter
pSource->Buffer = buffer;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
@@ -582,7 +638,10 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
pSource->lOffset = lValue;
if(pSource->state == AL_PLAYING || pSource->state == AL_PAUSED)
ApplyOffset(pSource, AL_TRUE);
{
if(ApplyOffset(pSource) == AL_FALSE)
alSetError(AL_INVALID_VALUE);
}
}
else
alSetError(AL_INVALID_VALUE);
@@ -599,6 +658,7 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
}
else
memcpy(&pSource->DirectFilter, filter, sizeof(*filter));
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
@@ -606,21 +666,30 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
case AL_DIRECT_FILTER_GAINHF_AUTO:
if(lValue == AL_TRUE || lValue == AL_FALSE)
{
pSource->DryGainHFAuto = lValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
if(lValue == AL_TRUE || lValue == AL_FALSE)
{
pSource->WetGainAuto = lValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
if(lValue == AL_TRUE || lValue == AL_FALSE)
{
pSource->WetGainHFAuto = lValue;
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
@@ -633,7 +702,11 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
lValue == AL_LINEAR_DISTANCE_CLAMPED ||
lValue == AL_EXPONENT_DISTANCE ||
lValue == AL_EXPONENT_DISTANCE_CLAMPED)
{
pSource->DistanceModel = lValue;
if(pContext->SourceDistanceModel)
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
break;
@@ -694,6 +767,7 @@ ALAPI void ALAPIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, AL
}
else
memcpy(&pSource->Send[lValue2].WetFilter, ALFilter, sizeof(*ALFilter));
pSource->NeedsUpdate = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
@@ -1250,7 +1324,6 @@ ALAPI void ALAPIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValue
ALAPI ALvoid ALAPIENTRY alSourcePlay(ALuint source)
{
alSourcePlayv(1, &source);
return;
}
ALAPI ALvoid ALAPIENTRY alSourcePlayv(ALsizei n, const ALuint *pSourceList)
@@ -1320,7 +1393,7 @@ ALAPI ALvoid ALAPIENTRY alSourcePlayv(ALsizei n, const ALuint *pSourceList)
// Check if an Offset has been set
if(pSource->lOffset)
ApplyOffset(pSource, AL_FALSE);
ApplyOffset(pSource);
if(pSource->BuffersPlayed == 0 && pSource->position == 0 &&
pSource->position_fraction == 0)
@@ -1354,7 +1427,6 @@ ALAPI ALvoid ALAPIENTRY alSourcePlayv(ALsizei n, const ALuint *pSourceList)
ALAPI ALvoid ALAPIENTRY alSourcePause(ALuint source)
{
alSourcePausev(1, &source);
return;
}
ALAPI ALvoid ALAPIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
@@ -1402,7 +1474,6 @@ ALAPI ALvoid ALAPIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
ALAPI ALvoid ALAPIENTRY alSourceStop(ALuint source)
{
alSourceStopv(1, &source);
return;
}
ALAPI ALvoid ALAPIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
@@ -1454,7 +1525,6 @@ ALAPI ALvoid ALAPIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
ALAPI ALvoid ALAPIENTRY alSourceRewind(ALuint source)
{
alSourceRewindv(1, &source);
return;
}
ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
@@ -1518,6 +1588,7 @@ ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, const AL
ALint iFrequency;
ALint iFormat;
ALboolean bBuffersValid = AL_TRUE;
ALboolean hadFormat = AL_FALSE;
if (n == 0)
return;
@@ -1546,6 +1617,7 @@ ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, const AL
{
iFrequency = ALBufferList->buffer->frequency;
iFormat = ALBufferList->buffer->format;
hadFormat = AL_TRUE;
break;
}
ALBufferList = ALBufferList->next;
@@ -1630,6 +1702,10 @@ ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, const AL
// Update number of buffers in queue
ALSource->BuffersInQueue += n;
// If no previous format, mark the source dirty now that it may
// have one
if(!hadFormat)
ALSource->NeedsUpdate = AL_TRUE;
}
}
else
@@ -1715,7 +1791,7 @@ ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint
}
static ALvoid InitSourceParams(ALCcontext *Context, ALsource *pSource)
static ALvoid InitSourceParams(ALsource *pSource)
{
pSource->flInnerAngle = 360.0f;
pSource->flOuterAngle = 360.0f;
@@ -1746,11 +1822,15 @@ static ALvoid InitSourceParams(ALCcontext *Context, ALsource *pSource)
pSource->RoomRolloffFactor = 0.0f;
pSource->DopplerFactor = 1.0f;
pSource->DistanceModel = Context->DistanceModel;
pSource->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
pSource->Resampler = DefaultResampler;
pSource->state = AL_INITIAL;
pSource->lSourceType = AL_UNDETERMINED;
pSource->NeedsUpdate = AL_TRUE;
pSource->Buffer = NULL;
}
@@ -1766,7 +1846,7 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
ALbufferlistitem *pBufferList;
ALbuffer *pBuffer;
ALfloat flBufferFreq;
ALint lChannels;
ALint lChannels, lBytes;
ALint readPos, writePos;
ALenum eOriginalFormat;
ALboolean bReturn = AL_TRUE;
@@ -1780,9 +1860,10 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
flBufferFreq = (ALfloat)pBuffer->frequency;
eOriginalFormat = pBuffer->eOriginalFormat;
lChannels = aluChannelsFromFormat(pBuffer->format);
lBytes = aluBytesFromFormat(pBuffer->format);
// Get Current BytesPlayed
readPos = pSource->position * lChannels * 2; // NOTE : This is the byte offset into the *current* buffer
readPos = pSource->position * lChannels * lBytes; // NOTE : This is the byte offset into the *current* buffer
// Add byte length of any processed buffers in the queue
pBufferList = pSource->queue;
for(i = 0;i < pSource->BuffersPlayed && pBufferList;i++)
@@ -1792,7 +1873,7 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
}
if(pSource->state == AL_PLAYING)
writePos = readPos + (updateSize * lChannels * 2);
writePos = readPos + (updateSize * lChannels * lBytes);
else
writePos = readPos;
@@ -1833,13 +1914,13 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
{
case AL_SEC_OFFSET:
case AL_SEC_RW_OFFSETS_EXT:
pflOffset[0] = (ALfloat)readPos / (lChannels * 2.0f * flBufferFreq);
pflOffset[1] = (ALfloat)writePos / (lChannels * 2.0f * flBufferFreq);
pflOffset[0] = (ALfloat)readPos / (lChannels * lBytes * flBufferFreq);
pflOffset[1] = (ALfloat)writePos / (lChannels * lBytes * flBufferFreq);
break;
case AL_SAMPLE_OFFSET:
case AL_SAMPLE_RW_OFFSETS_EXT:
pflOffset[0] = (ALfloat)(readPos / (lChannels * 2));
pflOffset[1] = (ALfloat)(writePos / (lChannels * 2));
pflOffset[0] = (ALfloat)(readPos / (lChannels * lBytes));
pflOffset[1] = (ALfloat)(writePos / (lChannels * lBytes));
break;
case AL_BYTE_OFFSET:
case AL_BYTE_RW_OFFSETS_EXT:
@@ -1848,39 +1929,35 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
(eOriginalFormat == AL_FORMAT_STEREO_IMA4))
{
// Round down to nearest ADPCM block
pflOffset[0] = (ALfloat)((readPos / (65 * 2 * lChannels)) * 36 * lChannels);
pflOffset[0] = (ALfloat)((readPos / (65 * lBytes * lChannels)) * 36 * lChannels);
if(pSource->state == AL_PLAYING)
{
// Round up to nearest ADPCM block
pflOffset[1] = (ALfloat)(((writePos + (65 * 2 * lChannels) - 1) / (65 * 2 * lChannels)) * 36 * lChannels);
pflOffset[1] = (ALfloat)(((writePos + (65 * lBytes * lChannels) - 1) / (65 * lBytes * lChannels)) * 36 * lChannels);
}
else
pflOffset[1] = pflOffset[0];
}
else if (eOriginalFormat == AL_FORMAT_REAR8)
{
pflOffset[0] = (ALfloat)(readPos >> 2);
pflOffset[1] = (ALfloat)(writePos >> 2);
pflOffset[0] = (ALfloat)(readPos / 2 / lBytes * 1);
pflOffset[1] = (ALfloat)(writePos / 2 / lBytes * 1);
}
else if (eOriginalFormat == AL_FORMAT_REAR16)
{
pflOffset[0] = (ALfloat)(readPos >> 1);
pflOffset[1] = (ALfloat)(writePos >> 1);
pflOffset[0] = (ALfloat)(readPos / 2 / lBytes * 2);
pflOffset[1] = (ALfloat)(writePos / 2 / lBytes * 2);
}
else if (aluBytesFromFormat(eOriginalFormat) == 1)
else if (eOriginalFormat == AL_FORMAT_REAR32)
{
pflOffset[0] = (ALfloat)(readPos >> 1);
pflOffset[1] = (ALfloat)(writePos >> 1);
}
else if (aluBytesFromFormat(eOriginalFormat) == 4)
{
pflOffset[0] = (ALfloat)(readPos << 1);
pflOffset[1] = (ALfloat)(writePos << 1);
pflOffset[0] = (ALfloat)(readPos / 2 / lBytes * 4);
pflOffset[1] = (ALfloat)(writePos / 2 / lBytes * 4);
}
else
{
pflOffset[0] = (ALfloat)readPos;
pflOffset[1] = (ALfloat)writePos;
ALuint OrigBytes = aluBytesFromFormat(eOriginalFormat);
pflOffset[0] = (ALfloat)(readPos / lBytes * OrigBytes);
pflOffset[1] = (ALfloat)(writePos / lBytes * OrigBytes);
}
break;
}
@@ -1901,7 +1978,7 @@ static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOf
Apply a playback offset to the Source. This function will update the queue (to correctly
mark buffers as 'pending' or 'processed' depending upon the new offset.
*/
static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext)
static ALboolean ApplyOffset(ALsource *pSource)
{
ALbufferlistitem *pBufferList;
ALbuffer *pBuffer;
@@ -1911,50 +1988,46 @@ static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext)
// Get true byte offset
lByteOffset = GetByteOffset(pSource);
// If this is a valid offset apply it
if (lByteOffset != -1)
// If the offset is invalid, don't apply it
if(lByteOffset == -1)
return AL_FALSE;
// Sort out the queue (pending and processed states)
pBufferList = pSource->queue;
lTotalBufferSize = 0;
pSource->BuffersPlayed = 0;
while(pBufferList)
{
// Sort out the queue (pending and processed states)
pBufferList = pSource->queue;
lTotalBufferSize = 0;
pSource->BuffersPlayed = 0;
while (pBufferList)
pBuffer = pBufferList->buffer;
lBufferSize = pBuffer ? pBuffer->size : 0;
if(lTotalBufferSize+lBufferSize <= lByteOffset)
{
pBuffer = pBufferList->buffer;
lBufferSize = pBuffer ? pBuffer->size : 0;
if ((lTotalBufferSize + lBufferSize) <= lByteOffset)
{
// Offset is past this buffer so increment BuffersPlayed
pSource->BuffersPlayed++;
}
else if (lTotalBufferSize <= lByteOffset)
{
// Offset is within this buffer
// Set Current Buffer
pSource->Buffer = pBufferList->buffer;
// SW Mixer Positions are in Samples
pSource->position = (lByteOffset - lTotalBufferSize) /
aluBytesFromFormat(pBuffer->format) /
aluChannelsFromFormat(pBuffer->format);
}
// Increment the TotalBufferSize
lTotalBufferSize += lBufferSize;
// Move on to next buffer in the Queue
pBufferList = pBufferList->next;
// Offset is past this buffer so increment BuffersPlayed
pSource->BuffersPlayed++;
}
}
else
{
if (bUpdateContext)
alSetError(AL_INVALID_VALUE);
else if(lTotalBufferSize <= lByteOffset)
{
// Offset is within this buffer
// Set Current Buffer
pSource->Buffer = pBufferList->buffer;
// SW Mixer Positions are in Samples
pSource->position = (lByteOffset - lTotalBufferSize) /
aluBytesFromFormat(pBuffer->format) /
aluChannelsFromFormat(pBuffer->format);
break;
}
// Increment the TotalBufferSize
lTotalBufferSize += lBufferSize;
// Move on to next buffer in the Queue
pBufferList = pBufferList->next;
}
// Clear Offset
pSource->lOffset = 0;
return AL_TRUE;
}
@@ -1963,16 +2036,17 @@ static void ApplyOffset(ALsource *pSource, ALboolean bUpdateContext)
Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond
offset supplied by the application). This takes into account the fact that the buffer format
may have been modifed by AL (e.g 8bit samples are converted to 16bit)
may have been modifed by AL (e.g 8bit samples are converted to float)
*/
static ALint GetByteOffset(ALsource *pSource)
{
ALbuffer *pBuffer = NULL;
ALbufferlistitem *pBufferList;
ALfloat flBufferFreq;
ALint lChannels;
ALint lChannels, lBytes;
ALint lByteOffset = -1;
ALint lTotalBufferDataSize;
ALenum OriginalFormat;
// Find the first non-NULL Buffer in the Queue
pBufferList = pSource->queue;
@@ -1990,56 +2064,54 @@ static ALint GetByteOffset(ALsource *pSource)
{
flBufferFreq = ((ALfloat)pBuffer->frequency);
lChannels = aluChannelsFromFormat(pBuffer->format);
lBytes = aluBytesFromFormat(pBuffer->format);
OriginalFormat = pBuffer->eOriginalFormat;
// Determine the ByteOffset (and ensure it is block aligned)
switch (pSource->lOffsetType)
{
case AL_BYTE_OFFSET:
// Take into consideration the original format
if ((pBuffer->eOriginalFormat == AL_FORMAT_MONO_IMA4) ||
(pBuffer->eOriginalFormat == AL_FORMAT_STEREO_IMA4))
if(OriginalFormat == AL_FORMAT_MONO_IMA4 ||
OriginalFormat == AL_FORMAT_STEREO_IMA4)
{
// Round down to nearest ADPCM block
lByteOffset = (pSource->lOffset / (36 * lChannels)) * 36 * lChannels;
lByteOffset = pSource->lOffset / (36 * lChannels);
// Multiply by compression rate
lByteOffset = (ALint)(3.6111f * (ALfloat)lByteOffset);
lByteOffset -= (lByteOffset % (lChannels * 2));
lByteOffset = lByteOffset * 65 * lChannels * lBytes;
lByteOffset -= (lByteOffset % (lChannels * lBytes));
}
else if (pBuffer->eOriginalFormat == AL_FORMAT_REAR8)
else if(OriginalFormat == AL_FORMAT_REAR8)
{
lByteOffset = pSource->lOffset * 4;
lByteOffset -= (lByteOffset % (lChannels * 2));
lByteOffset = pSource->lOffset / 1 * lBytes * 2;
lByteOffset -= (lByteOffset % (lChannels * lBytes));
}
else if (pBuffer->eOriginalFormat == AL_FORMAT_REAR16)
else if(OriginalFormat == AL_FORMAT_REAR16)
{
lByteOffset = pSource->lOffset * 2;
lByteOffset -= (lByteOffset % (lChannels * 2));
lByteOffset = pSource->lOffset / 2 * lBytes * 2;
lByteOffset -= (lByteOffset % (lChannels * lBytes));
}
else if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 1)
else if(OriginalFormat == AL_FORMAT_REAR32)
{
lByteOffset = pSource->lOffset * 2;
lByteOffset -= (lByteOffset % (lChannels * 2));
}
else if (aluBytesFromFormat(pBuffer->eOriginalFormat) == 4)
{
lByteOffset = pSource->lOffset / 2;
lByteOffset -= (lByteOffset % (lChannels * 2));
lByteOffset = pSource->lOffset / 4 * lBytes * 2;
lByteOffset -= (lByteOffset % (lChannels * lBytes));
}
else
{
lByteOffset = pSource->lOffset;
lByteOffset -= (lByteOffset % (lChannels * 2));
ALuint OrigBytes = aluBytesFromFormat(OriginalFormat);
lByteOffset = pSource->lOffset / OrigBytes * lBytes;
lByteOffset -= (lByteOffset % (lChannels * lBytes));
}
break;
case AL_SAMPLE_OFFSET:
lByteOffset = pSource->lOffset * lChannels * 2;
lByteOffset = pSource->lOffset * lChannels * lBytes;
break;
case AL_SEC_OFFSET:
// Note - lOffset is internally stored as Milliseconds
lByteOffset = (ALint)(pSource->lOffset * lChannels * 2.0f * flBufferFreq / 1000.0f);
lByteOffset -= (lByteOffset % (lChannels * 2));
lByteOffset = (ALint)(pSource->lOffset / 1000.0f * flBufferFreq);
lByteOffset *= lChannels * lBytes;
break;
}
@@ -2057,6 +2129,9 @@ static ALint GetByteOffset(ALsource *pSource)
lByteOffset = -1;
}
// Clear Offset
pSource->lOffset = 0;
return lByteOffset;
}
+92 -3
View File
@@ -44,34 +44,66 @@ static const ALchar alErrOutOfMemory[] = "Out of Memory";
ALAPI ALvoid ALAPIENTRY alEnable(ALenum capability)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context = GetContextSuspended();
if(!Context) return;
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
Context->SourceDistanceModel = AL_TRUE;
updateSources = AL_TRUE;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
if(updateSources)
{
ALsource *source = Context->Source;
while(source)
{
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alDisable(ALenum capability)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context = GetContextSuspended();
if(!Context) return;
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
Context->SourceDistanceModel = AL_FALSE;
updateSources = AL_TRUE;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
}
if(updateSources)
{
ALsource *source = Context->Source;
while(source)
{
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(Context);
}
@@ -85,6 +117,10 @@ ALAPI ALboolean ALAPIENTRY alIsEnabled(ALenum capability)
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
value = Context->SourceDistanceModel;
break;
default:
alSetError(AL_INVALID_ENUM);
break;
@@ -499,52 +535,96 @@ ALAPI const ALchar* ALAPIENTRY alGetString(ALenum pname)
ALAPI ALvoid ALAPIENTRY alDopplerFactor(ALfloat value)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context = GetContextSuspended();
if(!Context) return;
if(value >= 0.0f)
{
Context->DopplerFactor = value;
updateSources = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
// Force updating the sources for these parameters, since even head-
// relative sources are affected
if(updateSources)
{
ALsource *source = Context->Source;
while(source)
{
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alDopplerVelocity(ALfloat value)
{
ALCcontext *Context;
ALboolean updateSources = AL_FALSE;
Context = GetContextSuspended();
if(!Context) return;
if(value > 0.0f)
{
Context->DopplerVelocity=value;
updateSources = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
if(updateSources)
{
ALsource *source = Context->Source;
while(source)
{
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(Context);
}
ALAPI ALvoid ALAPIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
{
ALCcontext *pContext;
ALboolean updateSources = AL_FALSE;
pContext = GetContextSuspended();
if(!pContext) return;
if(flSpeedOfSound > 0.0f)
{
pContext->flSpeedOfSound = flSpeedOfSound;
updateSources = AL_TRUE;
}
else
alSetError(AL_INVALID_VALUE);
if(updateSources)
{
ALsource *source = pContext->Source;
while(source)
{
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(pContext);
}
ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
{
ALCcontext *Context;
ALsource *Source;
ALboolean updateSources = AL_FALSE;
Context = GetContextSuspended();
if(!Context) return;
@@ -559,8 +639,7 @@ ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
case AL_EXPONENT_DISTANCE:
case AL_EXPONENT_DISTANCE_CLAMPED:
Context->DistanceModel = value;
for(Source = Context->Source;Source != NULL;Source = Source->next)
Source->DistanceModel = value;
updateSources = !Context->SourceDistanceModel;
break;
default:
@@ -568,5 +647,15 @@ ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
break;
}
if(updateSources)
{
ALsource *source = Context->Source;
while(source)
{
source->NeedsUpdate = AL_TRUE;
source = source->next;
}
}
ProcessContext(Context);
}
+20
View File
@@ -0,0 +1,20 @@
Source Install
==============
To install OpenAL Soft, use your favorite shell to go into the build/
directory, and run:
cmake ..
Assuming configuration went well, you can then build it, typically using GNU
Make (KDevelop, MSVC, and others are possible depending on your system setup
and CMake configuration).
Please Note: Double check that the appropriate backends were detected. Often,
complaints of no sound, crashing, and missing devices can be solved by making
sure the correct backends are being used. CMake's output will identify which
backends were enabled.
For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio
were detected (if your target system uses them). For Windows, make sure
DirectSound was detected.
+38 -3
View File
@@ -48,10 +48,35 @@
# stereo modes.
#cf_level = 0
## head_dampen:
# Sets the amount of dampening on sounds emanating from behind the listener.
# This is used to simulate the natural occlusion of the head, which is
# typically missing with mono and stereo output, and as such, only works on
# mono and stereo output modes. Valid values range from 0 to 1 (inclusive),
# and higher values provide a stronger effect.
#head_dampen = 0.25
## frequency:
# Sets the output frequency.
#frequency = 44100
## resampler:
# Selects the resampler used when mixing sources. Valid values are:
# 0 - None (nearest sample, no interpolation)
# 1 - Linear (extrapolates samples using a linear slope between samples)
# 2 - Cosine (extrapolates using a (co)sine slope)
# Specifying other values will result in using the default (linear).
#resampler = 1
## rt-prio:
# Sets real-time priority for the mixing thread. Not all drivers may use this
# (eg. PulseAudio) as they already control the priority of the mixing thread.
# 0 and negative values will disable it. Note that this may constitute a
# security risk since a real-time priority thread can indefinitely block
# normal-priority threads if it fails to wait. As such, the default is
# disabled.
#rt-prio = 0
## period_size:
# Sets the update period size, in frames. This is the number of frames needed
# for each mixing update. If the deprecated 'refresh' option is specified and
@@ -79,9 +104,11 @@
## 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.
#drivers = alsa,oss,solaris,dsound,winmm,port,pulse,wave
# duplicated names are ignored. Unlisted backends won't be considered for use
# unless the list is ended with a comma (eg. 'oss,' will list OSS first
# followed by all other available backends, while 'oss' will list OSS only).
# An empty list means the default.
#drivers = pulse,alsa,oss,solaris,dsound,winmm,port,wave
## excludefx:
# Sets which effects to exclude, preventing apps from using them. This can
@@ -201,6 +228,14 @@
##
[pulse]
## spawn-server:
# Attempts to spawn a PulseAudio server when requesting to open a PulseAudio
# device. Note that some apps may open and probe all enumerated devices on
# startup, causing a server to spawn even if a PulseAudio device is not
# actually selected. Setting autospawn to false in Pulse's client.conf will
# still prevent autospawning even if this is set to true.
#spawn-server = false
##
## Wave File Writer stuff
##
+59
View File
@@ -0,0 +1,59 @@
# - Check if the C source code provided in the SOURCE argument compiles.
# CHECK_C_SOURCE_COMPILES(SOURCE VAR)
#
# FLAG - compiler flag to check
# VAR - variable to store whether the source code compiled
#
# The following variables may be set before calling this macro to
# modify the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
MACRO(CHECK_C_COMPILER_FLAG FLAG VAR)
IF("${VAR}" MATCHES "^${VAR}$")
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
"${FLAG} ${CMAKE_REQUIRED_FLAGS}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_C_COMPILER_FLAG_ADD_LIBRARIES
"-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}")
ELSE(CMAKE_REQUIRED_LIBRARIES)
SET(CHECK_C_COMPILER_FLAG_ADD_LIBRARIES)
ENDIF(CMAKE_REQUIRED_LIBRARIES)
IF(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_C_COMPILER_FLAG_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
ELSE(CMAKE_REQUIRED_INCLUDES)
SET(CHECK_C_COMPILER_FLAG_ADD_INCLUDES)
ENDIF(CMAKE_REQUIRED_INCLUDES)
FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c"
"int main() {return 0;}\n")
MESSAGE(STATUS "Checking if C compiler supports ${FLAG}")
TRY_COMPILE(${VAR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CHECK_C_COMPILER_FLAG_ADD_LIBRARIES}"
"${CHECK_C_COMPILER_FLAG_ADD_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
IF(${VAR})
SET(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
MESSAGE(STATUS "Checking if C compiler supports ${FLAG} - Success")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n")
ELSE(${VAR})
MESSAGE(STATUS "Checking if C compiler supports ${FLAG} - Failed")
SET(${VAR} "" CACHE INTERNAL "Test ${VAR}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n")
ENDIF(${VAR})
ENDIF("${VAR}" MATCHES "^${VAR}$")
ENDMACRO(CHECK_C_COMPILER_FLAG)
+9
View File
@@ -28,6 +28,9 @@
/* Define if we have dlfcn.h */
#cmakedefine HAVE_DLFCN_H
/* Define if we have the stat function */
#cmakedefine HAVE_STAT
/* Define if we have the sqrtf function */
#cmakedefine HAVE_SQRTF
@@ -64,6 +67,9 @@
/* Define if we have GCC's destructor attribute */
#cmakedefine HAVE_GCC_DESTRUCTOR
/* Define if we have GCC's format attribute */
#cmakedefine HAVE_GCC_FORMAT
/* Define if we have pthread_np.h */
#cmakedefine HAVE_PTHREAD_NP_H
@@ -79,4 +85,7 @@
/* Define if we have _controlfp() */
#cmakedefine HAVE__CONTROLFP
/* Define if we have pthread_setschedparam() */
#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM
#endif
+77 -71
View File
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "AL/alc.h"
#include "AL/al.h"
@@ -67,18 +68,18 @@ static void indent(int *width)
printChar(' ', width);
}
static void printExtensions(const char *header, char separator, const char *extensions)
static void printList(const char *header, char separator, const char *list)
{
int width = 0, start = 0, end = 0;
printf("%s:\n", header);
if(extensions == NULL || extensions[0] == '\0')
if(list == NULL || list[0] == '\0')
return;
indent(&width);
while (1)
while(1)
{
if(extensions[end] == separator || extensions[end] == '\0')
if(list[end] == separator || list[end] == '\0')
{
if(width + end - start + 2 > maxmimumWidth)
{
@@ -87,14 +88,14 @@ static void printExtensions(const char *header, char separator, const char *exte
}
while(start < end)
{
printChar(extensions[start], &width);
printChar(list[start], &width);
start++;
}
if(extensions[end] == '\0')
if(list[end] == '\0')
break;
start++;
end++;
if(extensions[end] == '\0')
if(list[end] == '\0')
break;
printChar(',', &width);
printChar(' ', &width);
@@ -128,15 +129,14 @@ static void checkForErrors(void)
static void printDevices(ALCenum which, const char *kind)
{
const char *s = alcGetString(NULL, which);
checkForErrors();
printf("Available %sdevices:\n", kind);
while(*s != '\0')
{
printf("Available %s devices:\n", kind);
if(s == NULL || *s == '\0')
printf(" (none!)\n");
else do {
printf(" %s\n", s);
while(*s++ != '\0')
;
}
} while(*s != '\0');
}
static void printALCInfo (void)
@@ -144,33 +144,20 @@ static void printALCInfo (void)
ALCint major, minor;
ALCdevice *device;
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE)
{
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATE_ALL_EXT") == AL_TRUE)
printDevices(ALC_ALL_DEVICES_SPECIFIER, "playback ");
else
printDevices(ALC_DEVICE_SPECIFIER, "playback ");
printDevices(ALC_CAPTURE_DEVICE_SPECIFIER, "capture ");
}
else
printf("No device enumeration available\n");
printf("Default device: %s\n",
alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
printf("Default capture device: %s\n",
alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
device = alcGetContextsDevice(alcGetCurrentContext());
checkForErrors();
printf("Default device: %s\n",
alcGetString(device, ALC_DEFAULT_DEVICE_SPECIFIER));
printf("Default capture device: %s\n",
alcGetString(device, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER));
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor);
checkForErrors();
printf("ALC version: %d.%d\n", (int)major, (int)minor);
printExtensions("ALC extensions", ' ',
alcGetString(device, ALC_EXTENSIONS));
printList("ALC extensions", ' ', alcGetString(device, ALC_EXTENSIONS));
checkForErrors();
}
@@ -179,7 +166,7 @@ static void printALInfo(void)
printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER));
printf("OpenAL version string: %s\n", alGetString(AL_VERSION));
printExtensions("OpenAL extensions", ' ', alGetString(AL_EXTENSIONS));
printList("OpenAL extensions", ' ', alGetString(AL_EXTENSIONS));
checkForErrors();
}
@@ -189,37 +176,24 @@ static void printEFXInfo(void)
ALCdevice *device;
ALuint obj;
int i;
const struct {
ALenum type;
const char *name;
} effects[] = {
{ AL_EFFECT_EAXREVERB, "EAX Reverb" },
{ AL_EFFECT_REVERB, "Reverb" },
{ AL_EFFECT_CHORUS, "Chorus" },
{ AL_EFFECT_DISTORTION, "Distortion" },
{ AL_EFFECT_ECHO, "Echo" },
{ AL_EFFECT_FLANGER, "Flanger" },
{ AL_EFFECT_FREQUENCY_SHIFTER, "Frequency Shifter" },
{ AL_EFFECT_VOCAL_MORPHER, "Vocal Morpher" },
{ AL_EFFECT_PITCH_SHIFTER, "Pitch Shifter" },
{ AL_EFFECT_RING_MODULATOR, "Ring Modulator" },
{ AL_EFFECT_AUTOWAH, "Autowah" },
{ AL_EFFECT_COMPRESSOR, "Compressor" },
{ AL_EFFECT_EQUALIZER, "Equalizer" },
{ AL_EFFECT_NULL, NULL }
const ALenum effects[] = {
AL_EFFECT_EAXREVERB, AL_EFFECT_REVERB, AL_EFFECT_CHORUS,
AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER,
AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER,
AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR, AL_EFFECT_AUTOWAH,
AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER, AL_EFFECT_NULL
};
const struct {
ALenum type;
const char *name;
} filters[] = {
{ AL_FILTER_LOWPASS, "Low-pass" },
{ AL_FILTER_HIGHPASS, "High-pass" },
{ AL_FILTER_BANDPASS, "Band-pass" },
{ AL_FILTER_NULL, NULL }
char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger,"
"Frequency Shifter,Vocal Morpher,Pitch Shifter,"
"Ring Modulator,Autowah,Compressor,Equalizer,";
const ALenum filters[] = {
AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS,
AL_FILTER_NULL
};
char filterNames[] = "Low-pass,High-pass,Band-pass,";
char *current;
device = alcGetContextsDevice(alcGetCurrentContext());
if(alcIsExtensionPresent(device, (const ALCchar*)"ALC_EXT_EFX") == AL_FALSE)
{
printf("EFX not available\n");
@@ -251,35 +225,67 @@ static void printEFXInfo(void)
p_alGenFilters(1, &obj);
checkForErrors();
printf("Available filters:\n");
for(i = 0;filters[i].type != AL_FILTER_NULL;i++)
current = filterNames;
for(i = 0;filters[i] != AL_FILTER_NULL;i++)
{
p_alFilteri(obj, AL_FILTER_TYPE, filters[i].type);
char *next = strchr(current, ',');
p_alFilteri(obj, AL_FILTER_TYPE, filters[i]);
if(alGetError() == AL_NO_ERROR)
printf(" %s\n", filters[i].name);
current = next+1;
else
memmove(current, next+1, strlen(next));
}
p_alDeleteFilters(1, &obj);
checkForErrors();
printList("Supported filters", ',', filterNames);
p_alGenEffects(1, &obj);
checkForErrors();
printf("Available effects:\n");
for(i = 0;effects[i].type != AL_EFFECT_NULL;i++)
current = effectNames;
for(i = 0;effects[i] != AL_EFFECT_NULL;i++)
{
p_alEffecti(obj, AL_EFFECT_TYPE, effects[i].type);
char *next = strchr(current, ',');
p_alEffecti(obj, AL_EFFECT_TYPE, effects[i]);
if(alGetError() == AL_NO_ERROR)
printf(" %s\n", effects[i].name);
current = next+1;
else
memmove(current, next+1, strlen(next));
}
p_alDeleteEffects(1, &obj);
checkForErrors();
printList("Supported effects", ',', effectNames);
}
int main()
{
ALCdevice *device = alcOpenDevice(NULL);
ALCcontext *context = alcCreateContext(device, NULL);
alcMakeContextCurrent(context);
checkForErrors();
ALCdevice *device;
ALCcontext *context;
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATION_EXT") == AL_TRUE)
{
if(alcIsExtensionPresent(NULL, (const ALCchar*)"ALC_ENUMERATE_ALL_EXT") == AL_TRUE)
printDevices(ALC_ALL_DEVICES_SPECIFIER, "playback");
else
printDevices(ALC_DEVICE_SPECIFIER, "playback");
printDevices(ALC_CAPTURE_DEVICE_SPECIFIER, "capture");
}
else
printf("No device enumeration available\n");
device = alcOpenDevice(NULL);
if(!device)
{
printf("Failed to open a device!\n");
exit(EXIT_FAILURE);
}
context = alcCreateContext(device, NULL);
if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
{
printf("Failed to set a context!\n");
exit(EXIT_FAILURE);
}
printALCInfo();
printALInfo();
+1 -2
View File
@@ -117,8 +117,7 @@ typedef void ALvoid;
#define AL_CONE_OUTER_ANGLE 0x1002
/**
* Specify the pitch to be applied, either at source,
* or on mixer results, at listener.
* Specify the pitch to be applied at source.
* Range: [0.5-2.0]
* Default: 1.0
*/
+15 -4
View File
@@ -53,6 +53,12 @@ extern "C" {
#define AL_FORMAT_STEREO_FLOAT32 0x10011
#endif
#ifndef AL_EXT_double
#define AL_EXT_double 1
#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012
#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013
#endif
#ifndef ALC_LOKI_audio_channel
#define ALC_LOKI_audio_channel 1
#define ALC_CHAN_MAIN_LOKI 0x500001
@@ -99,8 +105,8 @@ extern "C" {
typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATAEXTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei);
#endif
#ifndef AL_EXT_BUFFER_DATA_STATIC
#define AL_EXT_BUFFER_DATA_STATIC 1
#ifndef AL_EXT_STATIC_BUFFER
#define AL_EXT_STATIC_BUFFER 1
typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei);
#endif
@@ -146,8 +152,13 @@ typedef ALvoid (AL_APIENTRY*PFNALUNMAPDATABUFFEREXTPROC)(ALuint uiBuffer);
#ifndef ALC_EXT_thread_local_context
#define ALC_EXT_thread_local_context 1
typedef ALCboolean (ALCAPIENTRY*PFNALCMAKECURRENTPROC)(ALCcontext *context);
typedef ALCcontext* (ALCAPIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);
typedef ALCboolean (ALC_APIENTRY*PFNALCMAKECURRENTPROC)(ALCcontext *context);
typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void);
#endif
#ifndef AL_EXT_source_distance_model
#define AL_EXT_source_distance_model 1
#define AL_SOURCE_DISTANCE_MODEL 0x200
#endif
#ifdef __cplusplus