Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ad86a1c1b | |||
| 931f5875cd | |||
| f22b02a762 | |||
| 505f61ff43 | |||
| 0c2efa1253 | |||
| 5921e18be2 | |||
| 5b9e6fe440 | |||
| 35ba7d70dc | |||
| 026b4b8f4c | |||
| c924a50bed | |||
| 574792d2e1 | |||
| ab2eb5a603 | |||
| 3d7f925d52 | |||
| 93b584ff84 | |||
| 705849ca73 | |||
| 1a57f095e8 | |||
| ac9c2e8c4a | |||
| 45f8efec41 | |||
| ef7df2416d | |||
| cb113315f7 | |||
| d61f90a9c2 | |||
| 3d11fb219e | |||
| 4d9a368f96 | |||
| 43220b604c | |||
| 91f28fa87c | |||
| 82547db2db | |||
| 64ac3a4739 | |||
| c90616b963 | |||
| 0ceaa01c3d | |||
| 7d7e503603 | |||
| 7ee81eac0f | |||
| c9a08fc7b2 | |||
| 69ab93a824 | |||
| 179b660eee | |||
| a0ef7be9a5 | |||
| 2a735b14dc | |||
| a294dd8d9b | |||
| dc1522282b | |||
| 528a4c6a02 | |||
| 1770a8b62b | |||
| 77a0a6de95 | |||
| c1fd977e79 | |||
| cbbda93292 | |||
| c6340ce12d | |||
| 7bc739e965 | |||
| 9f988808c7 | |||
| 6e9ce47a4b | |||
| 89f59c0e1c | |||
| 3793919892 | |||
| d1699d50f6 | |||
| b94d950b1e | |||
| d3e77a0f63 | |||
| 965a71ee90 | |||
| fd794b44b2 | |||
| c9dcba17a9 | |||
| 88de4e15b3 | |||
| 7f0c6629b9 | |||
| f6ca39403d | |||
| ea7cf35ea4 | |||
| accea119d9 | |||
| 6ea7b43c90 | |||
| ddfad996a9 | |||
| d786f99094 | |||
| 008563450c | |||
| 69c238a2e6 | |||
| b3fdf170b1 | |||
| 56cc038603 | |||
| 4c83c689a8 | |||
| 2b7953c472 | |||
| 368ef1cea9 | |||
| bd696a6b37 | |||
| a9fc272e39 | |||
| c5952d1ddc | |||
| 656a406377 | |||
| 5fcd6cc510 | |||
| e09b6020a6 | |||
| 84d2d623b6 | |||
| 1694e5bd12 | |||
| 5170e251f9 | |||
| 4697e946d3 | |||
| 9286e3984c | |||
| 88f3d747b7 | |||
| d4427c54ea | |||
| 92ade80557 | |||
| 8138446b8c | |||
| 58ecc7fad4 | |||
| 311cc5c62f | |||
| 4a928ea9fa | |||
| c1eb444a39 | |||
| b5270e0bb3 | |||
| 6cfc31777b | |||
| 0e1e8503e0 | |||
| 974d0b4e91 | |||
| d66832a39c | |||
| d5889a941f | |||
| 6248e986e5 | |||
| 786b98a013 | |||
| f63d8dbf38 | |||
| 15aad09ce7 | |||
| fdd314f7f8 | |||
| 39b456d88c | |||
| d930fb8d3d | |||
| 3ec64eb0fd | |||
| d81c9819b8 | |||
| 98ce1d14c1 | |||
| 69f9ab88b9 | |||
| 1a0676f0eb | |||
| 658923175f | |||
| 877f4340ba | |||
| 35a9ccb41f | |||
| c7c2f9385f | |||
| d1f3dbb9a1 | |||
| cfb30fe975 | |||
| 2d1b378ef2 | |||
| 06bbee2449 | |||
| 85bc300dfa | |||
| 0662adacb9 | |||
| 65a153da6c | |||
| c5ee010640 | |||
| 1b18b4a0ee | |||
| 58765aab6b | |||
| 1483af1baa | |||
| 13979793f6 | |||
| 9c228e7625 | |||
| 6a667b36d1 | |||
| fe37f1968d | |||
| 4565bdd7ce | |||
| 5f3c07ca3b | |||
| 8d1da6a8ca | |||
| ff8e09495d | |||
| e868eef679 |
@@ -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, ¶m);
|
||||
}
|
||||
else
|
||||
{
|
||||
param.sched_priority = 0;
|
||||
failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, ¶m);
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
+12
-2
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+61
-55
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -11,7 +11,7 @@ extern "C" {
|
||||
|
||||
typedef struct ALbuffer
|
||||
{
|
||||
ALshort *data;
|
||||
ALfloat *data;
|
||||
ALsizei size;
|
||||
|
||||
ALenum format;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
##
|
||||
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user