Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 043fe6edd2 | |||
| ef68e5d0ff | |||
| c6f3a4e062 | |||
| 87ed53c7f6 | |||
| 89e9437b84 | |||
| 1454c46b5f | |||
| 0fac1e9115 | |||
| f3a3358e63 | |||
| 3c122b0bef | |||
| 7940003d06 | |||
| 45b16ff456 | |||
| 9341f4f884 | |||
| 2c20f26784 | |||
| 2a21a449b4 | |||
| 74dc7090fd | |||
| e12ac95d69 | |||
| 34ea7eba9e | |||
| 6d3ba44f55 | |||
| 5a8ad67660 | |||
| f1e442408b | |||
| a946af4463 | |||
| e01cd92d56 | |||
| 923af8c3a6 | |||
| ac04cf57fa | |||
| 1f6c4e01db | |||
| 04135723a2 | |||
| 93fbdb1e6c | |||
| c1de15f840 | |||
| 3be399c555 | |||
| 1f5453075c | |||
| 33a74f1594 | |||
| e4da1224cb | |||
| 5c2a47620c | |||
| 1bfa7609d2 | |||
| 7e8501123a | |||
| c447eeb2c7 | |||
| ad19cea6e0 | |||
| 0ce29863e3 | |||
| 7a7a4844f4 | |||
| a2adbb1ab5 | |||
| a97fc792d8 | |||
| e9a6a1d6f5 | |||
| f245f0ef87 | |||
| a30f431b63 | |||
| 58f48f20e2 | |||
| ee1b02b709 | |||
| 55c790c9ff | |||
| 65b69f3308 | |||
| c67fbd72dd | |||
| 30f57d0824 | |||
| 1c54018111 | |||
| e80e1b6d9f | |||
| 437f00d6de | |||
| fc6d6b1601 | |||
| 9306e36d52 | |||
| 61122a5093 | |||
| a8a4ff8af1 | |||
| 8a857c35ee | |||
| 89ddd7d8e5 | |||
| 8d0c4ccb3b | |||
| 8ee47d5573 | |||
| 9e88011417 | |||
| f8949ee7a1 | |||
| 62aa2d0ba7 | |||
| ace047d625 | |||
| d6277db209 | |||
| 7ebb28327f | |||
| 86931cbde4 | |||
| 6d7be151dc | |||
| 07227b9806 | |||
| 8348d719cd | |||
| 0fcefd865b | |||
| 57c2e9b5f8 | |||
| 7d7fc39035 | |||
| 351105b3df | |||
| cbfc33215b | |||
| 5a93b56673 | |||
| 1f4c69c17a | |||
| f5b19fad20 | |||
| bc60818e9a | |||
| f82c88f016 | |||
| 98e86decad | |||
| aaf2c0ebd4 | |||
| 778b74cae1 | |||
| 43ee1edd97 | |||
| dd7e23740b | |||
| 1acd6da745 | |||
| 3056f91ec5 | |||
| ed03570e1a | |||
| 2ec0e48d06 | |||
| 8b54d59b8c | |||
| f6a4dbabdd | |||
| a71c291bcb | |||
| 55b9ccc2de |
@@ -18,8 +18,6 @@
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
@@ -37,13 +35,7 @@
|
||||
#include "alExtension.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "bs2b.h"
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// DEBUG INFORMATION
|
||||
|
||||
char _alDebug[256];
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
#include "alu.h"
|
||||
|
||||
|
||||
#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
@@ -67,6 +59,12 @@ static struct {
|
||||
#ifdef HAVE_WINMM
|
||||
{ "winmm", alcWinMMInit, EmptyFuncs },
|
||||
#endif
|
||||
#ifdef HAVE_PORTAUDIO
|
||||
{ "port", alc_pa_init, EmptyFuncs },
|
||||
#endif
|
||||
#ifdef HAVE_PULSEAUDIO
|
||||
{ "pulse", alc_pulse_init, EmptyFuncs },
|
||||
#endif
|
||||
|
||||
{ "wave", alc_wave_init, EmptyFuncs },
|
||||
|
||||
@@ -317,7 +315,9 @@ static void InitAL(void)
|
||||
const char *name;
|
||||
int type;
|
||||
} EffectList[] = {
|
||||
{ "eaxreverb", EAXREVERB },
|
||||
{ "reverb", REVERB },
|
||||
{ "echo", ECHO },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
int n;
|
||||
@@ -475,7 +475,11 @@ static ALvoid InitContext(ALCcontext *pContext)
|
||||
pContext->lNumStereoSources = 1;
|
||||
pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
|
||||
|
||||
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_LOKI_quadriphonic";
|
||||
pContext->NumSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
|
||||
if(pContext->NumSends > MAX_SENDS)
|
||||
pContext->NumSends = MAX_SENDS;
|
||||
|
||||
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_source_distance_model AL_LOKI_quadriphonic";
|
||||
|
||||
level = GetConfigValueInt(NULL, "cf_level", 0);
|
||||
if(level > 0 && level <= 6)
|
||||
@@ -484,6 +488,8 @@ static ALvoid InitContext(ALCcontext *pContext)
|
||||
bs2b_set_srate(pContext->bs2b, pContext->Frequency);
|
||||
bs2b_set_level(pContext->bs2b, level);
|
||||
}
|
||||
|
||||
aluInitPanning(pContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -810,6 +816,8 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
|
||||
case ALC_MAX_AUXILIARY_SENDS:
|
||||
if(!size)
|
||||
SetALCError(ALC_INVALID_VALUE);
|
||||
else if(device && device->Context)
|
||||
*data = device->Context->NumSends;
|
||||
else
|
||||
*data = MAX_SENDS;
|
||||
break;
|
||||
@@ -851,7 +859,7 @@ ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsize
|
||||
data[i++] = device->Context->lNumStereoSources;
|
||||
|
||||
data[i++] = ALC_MAX_AUXILIARY_SENDS;
|
||||
data[i++] = MAX_SENDS;
|
||||
data[i++] = device->Context->NumSends;
|
||||
}
|
||||
ProcessContext(NULL);
|
||||
|
||||
@@ -1016,6 +1024,7 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
|
||||
{
|
||||
ALCcontext *ALContext = NULL;
|
||||
ALuint ulAttributeIndex, ulRequestedStereoSources;
|
||||
ALuint RequestedSends;
|
||||
|
||||
if ((device)&&(!device->IsCaptureDevice))
|
||||
{
|
||||
@@ -1045,7 +1054,7 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
|
||||
|
||||
ProcessContext(NULL);
|
||||
|
||||
// Check for Voice Count attributes
|
||||
// Check for attributes
|
||||
if (attrList)
|
||||
{
|
||||
ulAttributeIndex = 0;
|
||||
@@ -1060,7 +1069,16 @@ ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint
|
||||
|
||||
ALContext->lNumStereoSources = ulRequestedStereoSources;
|
||||
ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
|
||||
break;
|
||||
}
|
||||
|
||||
if(attrList[ulAttributeIndex] == ALC_MAX_AUXILIARY_SENDS)
|
||||
{
|
||||
RequestedSends = attrList[ulAttributeIndex + 1];
|
||||
|
||||
if(RequestedSends > ALContext->NumSends)
|
||||
RequestedSends = ALContext->NumSends;
|
||||
|
||||
ALContext->NumSends = RequestedSends;
|
||||
}
|
||||
|
||||
ulAttributeIndex += 2;
|
||||
@@ -1262,22 +1280,26 @@ ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
|
||||
if((ALint)device->MaxNoOfSources <= 0)
|
||||
device->MaxNoOfSources = 256;
|
||||
|
||||
device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
|
||||
if((ALint)device->AuxiliaryEffectSlotMax <= 0)
|
||||
device->AuxiliaryEffectSlotMax = 4;
|
||||
|
||||
// Find a playback device to open
|
||||
SuspendContext(NULL);
|
||||
for(i = 0;BackendList[i].Init;i++)
|
||||
{
|
||||
device->Funcs = &BackendList[i].Funcs;
|
||||
if(ALCdevice_OpenPlayback(device, deviceName))
|
||||
{
|
||||
SuspendContext(NULL);
|
||||
device->next = g_pDeviceList;
|
||||
g_pDeviceList = device;
|
||||
g_ulDeviceCount++;
|
||||
ProcessContext(NULL);
|
||||
|
||||
bDeviceFound = AL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ProcessContext(NULL);
|
||||
|
||||
if (!bDeviceFound)
|
||||
{
|
||||
|
||||
+5
-17
@@ -18,6 +18,10 @@
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WIN32_IE 0x400
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -27,8 +31,7 @@
|
||||
|
||||
#include "alMain.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WIN32_IE 0x400
|
||||
#ifdef _WIN32_IE
|
||||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
@@ -219,13 +222,6 @@ void ReadALConfig(void)
|
||||
}
|
||||
#else
|
||||
f = fopen("/etc/openal/alsoft.conf", "r");
|
||||
if(!f)
|
||||
{
|
||||
f = fopen("/etc/openal/config", "r");
|
||||
if(f)
|
||||
AL_PRINT("Reading /etc/openal/config; this file is deprecated\n"
|
||||
"\tPlease rename it to /etc/openal/alsoft.conf\n");
|
||||
}
|
||||
if(f)
|
||||
{
|
||||
LoadConfigFromFile(f);
|
||||
@@ -235,14 +231,6 @@ void ReadALConfig(void)
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", getenv("HOME"));
|
||||
f = fopen(buffer, "r");
|
||||
if(!f)
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "%s/.openalrc", getenv("HOME"));
|
||||
f = fopen(buffer, "r");
|
||||
if(f)
|
||||
AL_PRINT("Reading ~/.openalrc; this file is deprecated\n"
|
||||
"\tPlease rename it to ~/.alsoftrc\n");
|
||||
}
|
||||
if(f)
|
||||
{
|
||||
LoadConfigFromFile(f);
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 2009 by Chris Robinson.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alFilter.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alError.h"
|
||||
#include "alu.h"
|
||||
|
||||
typedef struct ALechoState {
|
||||
// Must be first in all effects!
|
||||
ALeffectState state;
|
||||
|
||||
ALfloat *SampleBuffer;
|
||||
ALuint BufferLength;
|
||||
|
||||
// The echo is two tap. The third tap is the offset to write the feedback
|
||||
// and input sample to
|
||||
struct {
|
||||
ALuint offset;
|
||||
} Tap[3];
|
||||
// The LR gains for the first tap. The second tap uses the reverse
|
||||
ALfloat GainL;
|
||||
ALfloat GainR;
|
||||
|
||||
ALfloat FeedGain;
|
||||
|
||||
FILTER iirFilter;
|
||||
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;
|
||||
if(state)
|
||||
{
|
||||
free(state->SampleBuffer);
|
||||
state->SampleBuffer = NULL;
|
||||
free(state);
|
||||
}
|
||||
}
|
||||
|
||||
ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, ALeffect *Effect)
|
||||
{
|
||||
ALechoState *state = (ALechoState*)effect;
|
||||
ALuint newdelay1, newdelay2;
|
||||
ALfloat lrpan, cw, a, g;
|
||||
|
||||
newdelay1 = (ALuint)(Effect->Echo.Delay * Context->Frequency);
|
||||
newdelay2 = (ALuint)(Effect->Echo.LRDelay * Context->Frequency);
|
||||
|
||||
state->Tap[0].offset = (state->BufferLength - newdelay1 - 1 +
|
||||
state->Tap[2].offset)%state->BufferLength;
|
||||
state->Tap[1].offset = (state->BufferLength - newdelay1 - newdelay2 - 1 +
|
||||
state->Tap[2].offset)%state->BufferLength;
|
||||
|
||||
lrpan = Effect->Echo.Spread*0.5f + 0.5f;
|
||||
state->GainL = aluSqrt( lrpan);
|
||||
state->GainR = aluSqrt(1.0f-lrpan);
|
||||
|
||||
state->FeedGain = Effect->Echo.Feedback;
|
||||
|
||||
cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Context->Frequency);
|
||||
g = 1.0f - Effect->Echo.Damping;
|
||||
a = 0.0f;
|
||||
if(g < 0.9999f) // 1-epsilon
|
||||
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
|
||||
state->iirFilter.coeff = a;
|
||||
}
|
||||
|
||||
ALvoid EchoProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
|
||||
{
|
||||
ALechoState *state = (ALechoState*)effect;
|
||||
const ALuint delay = state->BufferLength-1;
|
||||
ALuint tap1off = state->Tap[0].offset;
|
||||
ALuint tap2off = state->Tap[1].offset;
|
||||
ALuint fboff = state->Tap[2].offset;
|
||||
ALfloat gain = Slot->Gain;
|
||||
ALfloat samp[2];
|
||||
ALuint i;
|
||||
|
||||
for(i = 0;i < SamplesToDo;i++)
|
||||
{
|
||||
// Apply damping
|
||||
samp[0] = lpFilter2P(&state->iirFilter, 0, state->SampleBuffer[tap2off]+SamplesIn[i]);
|
||||
|
||||
// Apply feedback gain and mix in the new sample
|
||||
state->SampleBuffer[fboff] = samp[0] * state->FeedGain;
|
||||
|
||||
tap1off = (tap1off+1) & delay;
|
||||
tap2off = (tap2off+1) & delay;
|
||||
fboff = (fboff+1) & delay;
|
||||
|
||||
// Sample first tap
|
||||
samp[0] = state->SampleBuffer[tap1off]*state->GainL;
|
||||
samp[1] = state->SampleBuffer[tap1off]*state->GainR;
|
||||
// Sample second tap. Reverse LR panning
|
||||
samp[0] += state->SampleBuffer[tap2off]*state->GainR;
|
||||
samp[1] += state->SampleBuffer[tap2off]*state->GainL;
|
||||
// Apply slot gain
|
||||
samp[0] *= gain;
|
||||
samp[1] *= gain;
|
||||
|
||||
SamplesOut[i][FRONT_LEFT] += samp[0];
|
||||
SamplesOut[i][FRONT_RIGHT] += samp[1];
|
||||
SamplesOut[i][SIDE_LEFT] += samp[0];
|
||||
SamplesOut[i][SIDE_RIGHT] += samp[1];
|
||||
SamplesOut[i][BACK_LEFT] += samp[0];
|
||||
SamplesOut[i][BACK_RIGHT] += samp[1];
|
||||
}
|
||||
|
||||
state->Tap[0].offset = tap1off;
|
||||
state->Tap[1].offset = tap2off;
|
||||
state->Tap[2].offset = fboff;
|
||||
}
|
||||
|
||||
ALeffectState *EchoCreate(ALCcontext *Context)
|
||||
{
|
||||
ALechoState *state;
|
||||
ALuint i, maxlen;
|
||||
|
||||
state = malloc(sizeof(*state));
|
||||
if(!state)
|
||||
{
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->state.Destroy = EchoDestroy;
|
||||
state->state.Update = EchoUpdate;
|
||||
state->state.Process = EchoProcess;
|
||||
|
||||
maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Context->Frequency);
|
||||
maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Context->Frequency);
|
||||
|
||||
// Use the next power of 2 for the buffer length, so the tap offsets can be
|
||||
// wrapped using a mask instead of a modulo
|
||||
state->BufferLength = NextPowerOf2(maxlen+1);
|
||||
state->SampleBuffer = malloc(state->BufferLength * sizeof(ALfloat));
|
||||
if(!state->SampleBuffer)
|
||||
{
|
||||
free(state);
|
||||
alSetError(AL_OUT_OF_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i = 0;i < state->BufferLength;i++)
|
||||
state->SampleBuffer[i] = 0.0f;
|
||||
|
||||
state->Tap[0].offset = 0;
|
||||
state->Tap[1].offset = 0;
|
||||
state->Tap[2].offset = 0;
|
||||
state->GainL = 0.0f;
|
||||
state->GainR = 0.0f;
|
||||
|
||||
for(i = 0;i < 2;i++)
|
||||
state->iirFilter.history[i] = 0.0f;
|
||||
state->iirFilter.coeff = 0.0f;
|
||||
|
||||
return &state->state;
|
||||
}
|
||||
+539
-303
File diff suppressed because it is too large
Load Diff
+4
-2
@@ -81,10 +81,11 @@ ALsizei RingBufferSize(RingBuffer *ring)
|
||||
|
||||
void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
|
||||
{
|
||||
int remain = ring->length - ring->write_pos;
|
||||
int remain;
|
||||
|
||||
EnterCriticalSection(&ring->cs);
|
||||
|
||||
remain = ring->length - ring->write_pos;
|
||||
if((ring->read_pos-ring->write_pos+ring->length)%ring->length < len)
|
||||
ring->read_pos = (ring->write_pos+len) % ring->length;
|
||||
|
||||
@@ -104,10 +105,11 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
|
||||
|
||||
void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
|
||||
{
|
||||
int remain = ring->length - ring->read_pos;
|
||||
int remain;
|
||||
|
||||
EnterCriticalSection(&ring->cs);
|
||||
|
||||
remain = ring->length - ring->read_pos;
|
||||
if(remain < len)
|
||||
{
|
||||
memcpy(data, ring->mem+(ring->read_pos*ring->frame_size), remain*ring->frame_size);
|
||||
|
||||
+148
-107
@@ -74,6 +74,11 @@ MAKE_FUNC(snd_pcm_hw_params_get_buffer_size);
|
||||
MAKE_FUNC(snd_pcm_hw_params_get_period_size);
|
||||
MAKE_FUNC(snd_pcm_hw_params_get_access);
|
||||
MAKE_FUNC(snd_pcm_hw_params);
|
||||
MAKE_FUNC(snd_pcm_sw_params_malloc);
|
||||
MAKE_FUNC(snd_pcm_sw_params_current);
|
||||
MAKE_FUNC(snd_pcm_sw_params_set_avail_min);
|
||||
MAKE_FUNC(snd_pcm_sw_params);
|
||||
MAKE_FUNC(snd_pcm_sw_params_free);
|
||||
MAKE_FUNC(snd_pcm_prepare);
|
||||
MAKE_FUNC(snd_pcm_start);
|
||||
MAKE_FUNC(snd_pcm_resume);
|
||||
@@ -103,11 +108,10 @@ MAKE_FUNC(snd_ctl_card_info_get_name);
|
||||
MAKE_FUNC(snd_card_next);
|
||||
#undef MAKE_FUNC
|
||||
|
||||
#define MAX_DEVICES 16
|
||||
#define MAX_ALL_DEVICES 32
|
||||
|
||||
static ALCchar *alsaDevice;
|
||||
static DevMap allDevNameMap[MAX_ALL_DEVICES];
|
||||
static ALCchar *alsaDeviceList[MAX_DEVICES];
|
||||
static DevMap allCaptureDevNameMap[MAX_ALL_DEVICES];
|
||||
|
||||
static int xrun_recovery(snd_pcm_t *handle, int err)
|
||||
@@ -178,7 +182,7 @@ static ALuint ALSAProc(ALvoid *ptr)
|
||||
}
|
||||
|
||||
// make sure there's frames to process
|
||||
if(avail == 0)
|
||||
if(avail >= 0 && avail < (snd_pcm_sframes_t)pDevice->UpdateSize)
|
||||
{
|
||||
if(state != SND_PCM_STATE_RUNNING)
|
||||
{
|
||||
@@ -195,34 +199,37 @@ static ALuint ALSAProc(ALvoid *ptr)
|
||||
AL_PRINT("Wait timeout... buffer size too low?\n");
|
||||
continue;
|
||||
}
|
||||
avail = pDevice->UpdateSize;
|
||||
|
||||
// it is possible that contiguous areas are smaller, thus we use a loop
|
||||
while (avail > 0)
|
||||
{
|
||||
frames = avail;
|
||||
|
||||
SuspendContext(NULL);
|
||||
err = psnd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames);
|
||||
if (err < 0)
|
||||
{
|
||||
err = xrun_recovery(data->pcmHandle, err);
|
||||
if (err < 0)
|
||||
AL_PRINT("mmap begin error: %s\n", psnd_strerror(err));
|
||||
ProcessContext(NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
SuspendContext(NULL);
|
||||
WritePtr = (char*)areas->addr + (offset * areas->step / 8);
|
||||
WriteCnt = psnd_pcm_frames_to_bytes(data->pcmHandle, frames);
|
||||
aluMixData(pDevice->Context, WritePtr, WriteCnt, pDevice->Format);
|
||||
ProcessContext(NULL);
|
||||
|
||||
commitres = psnd_pcm_mmap_commit(data->pcmHandle, offset, frames);
|
||||
if (commitres < 0 || (commitres-frames) != 0)
|
||||
{
|
||||
AL_PRINT("mmap commit error: %s\n",
|
||||
psnd_strerror(commitres >= 0 ? -EPIPE : commitres));
|
||||
ProcessContext(NULL);
|
||||
break;
|
||||
}
|
||||
ProcessContext(NULL);
|
||||
|
||||
avail -= frames;
|
||||
}
|
||||
@@ -318,9 +325,11 @@ static ALuint ALSANoMMapCaptureProc(ALvoid *ptr)
|
||||
static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
snd_pcm_uframes_t bufferSizeInFrames;
|
||||
snd_pcm_sw_params_t *sp = NULL;
|
||||
snd_pcm_hw_params_t *p = NULL;
|
||||
snd_pcm_access_t access;
|
||||
unsigned int periods;
|
||||
unsigned int rate;
|
||||
alsa_data *data;
|
||||
char driver[64];
|
||||
const char *str;
|
||||
@@ -348,21 +357,15 @@ static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceNam
|
||||
goto open_alsa;
|
||||
}
|
||||
}
|
||||
for(idx = 0;idx < MAX_DEVICES;idx++)
|
||||
if(strcmp(deviceName, alsaDevice) == 0)
|
||||
{
|
||||
if(alsaDeviceList[idx] &&
|
||||
strcmp(deviceName, alsaDeviceList[idx]) == 0)
|
||||
{
|
||||
device->szDeviceName = alsaDeviceList[idx];
|
||||
if(idx > 0)
|
||||
sprintf(driver, "hw:%zd,0", idx-1);
|
||||
goto open_alsa;
|
||||
}
|
||||
device->szDeviceName = alsaDevice;
|
||||
goto open_alsa;
|
||||
}
|
||||
return ALC_FALSE;
|
||||
}
|
||||
else
|
||||
device->szDeviceName = alsaDeviceList[0];
|
||||
device->szDeviceName = alsaDevice;
|
||||
|
||||
open_alsa:
|
||||
data = (alsa_data*)calloc(1, sizeof(alsa_data));
|
||||
@@ -401,6 +404,7 @@ open_alsa:
|
||||
|
||||
periods = GetConfigValueInt("alsa", "periods", 0);
|
||||
bufferSizeInFrames = device->UpdateSize;
|
||||
rate = device->Frequency;
|
||||
|
||||
str = GetConfigValue("alsa", "mmap", "true");
|
||||
allowmmap = (strcasecmp(str, "true") == 0 ||
|
||||
@@ -408,25 +412,40 @@ open_alsa:
|
||||
strcasecmp(str, "on") == 0 ||
|
||||
atoi(str) != 0);
|
||||
|
||||
err = NULL;
|
||||
psnd_pcm_hw_params_malloc(&p);
|
||||
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
|
||||
/* start with the largest configuration space possible */
|
||||
if(!(ok(psnd_pcm_hw_params_any(data->pcmHandle, p), "any") &&
|
||||
/* set interleaved access */
|
||||
((allowmmap && ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access")) ||
|
||||
ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED), "set access")) &&
|
||||
/* set format (implicitly sets sample bits) */
|
||||
ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, data->format), "set format") &&
|
||||
/* set channels (implicitly sets frame bits) */
|
||||
ok(psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(device->Format)), "set channels") &&
|
||||
/* set periods (implicitly constrains period/buffer parameters) */
|
||||
(!periods || ok(psnd_pcm_hw_params_set_periods_near(data->pcmHandle, p, &periods, NULL), "set periods near")) &&
|
||||
/* set rate (implicitly constrains period/buffer parameters) */
|
||||
ok(psnd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &device->Frequency, NULL), "set rate near") &&
|
||||
/* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
|
||||
ok(psnd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames), "set buffer size near") &&
|
||||
/* install and prepare hardware configuration */
|
||||
ok(psnd_pcm_hw_params(data->pcmHandle, p), "set params")))
|
||||
|
||||
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=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, data->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(device->Format))) < 0)
|
||||
err = "set channels";
|
||||
/* set periods (implicitly constrains period/buffer parameters) */
|
||||
if(err == NULL && periods && (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)
|
||||
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)
|
||||
err = "set buffer size near";
|
||||
/* install and prepare hardware configuration */
|
||||
if(err == NULL && (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)
|
||||
err = "get access";
|
||||
if(err == NULL && (i=psnd_pcm_hw_params_get_period_size(p, &bufferSizeInFrames, NULL)) < 0)
|
||||
err = "get period size";
|
||||
if(err != NULL)
|
||||
{
|
||||
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
|
||||
psnd_pcm_hw_params_free(p);
|
||||
@@ -434,31 +453,30 @@ open_alsa:
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
#undef ok
|
||||
|
||||
if((i=psnd_pcm_hw_params_get_access(p, &access)) < 0)
|
||||
{
|
||||
AL_PRINT("get_access failed: %s\n", psnd_strerror(i));
|
||||
psnd_pcm_hw_params_free(p);
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
if((i=psnd_pcm_hw_params_get_period_size(p, &bufferSizeInFrames, NULL)) < 0)
|
||||
{
|
||||
AL_PRINT("get_period_size failed: %s\n", psnd_strerror(i));
|
||||
psnd_pcm_hw_params_free(p);
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
psnd_pcm_hw_params_free(p);
|
||||
|
||||
device->UpdateSize = bufferSizeInFrames;
|
||||
err = NULL;
|
||||
psnd_pcm_sw_params_malloc(&sp);
|
||||
|
||||
data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, device->UpdateSize);
|
||||
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, bufferSizeInFrames)) != 0)
|
||||
err = "sw set avail min";
|
||||
if(err == NULL && (i=psnd_pcm_sw_params(data->pcmHandle, sp)) != 0)
|
||||
err = "sw set params";
|
||||
if(err != NULL)
|
||||
{
|
||||
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
|
||||
psnd_pcm_sw_params_free(sp);
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
psnd_pcm_sw_params_free(sp);
|
||||
|
||||
data->size = psnd_pcm_frames_to_bytes(data->pcmHandle, bufferSizeInFrames);
|
||||
if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
|
||||
{
|
||||
data->buffer = malloc(data->size);
|
||||
@@ -498,6 +516,9 @@ open_alsa:
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->UpdateSize = bufferSizeInFrames;
|
||||
device->Frequency = rate;
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
@@ -593,44 +614,70 @@ open_alsa:
|
||||
strcasecmp(str, "on") == 0 ||
|
||||
atoi(str) != 0);
|
||||
|
||||
err = NULL;
|
||||
bufferSizeInFrames = SampleSize;
|
||||
psnd_pcm_hw_params_malloc(&p);
|
||||
#define ok(func, str) (i=(func),((i<0)?(err=(str)),0:1))
|
||||
/* start with the largest configuration space possible */
|
||||
if(!(allowmmap &&
|
||||
ok(psnd_pcm_hw_params_any(data->pcmHandle, p), "any") &&
|
||||
/* set interleaved access */
|
||||
ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED), "set access") &&
|
||||
/* set format (implicitly sets sample bits) */
|
||||
ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, alsaFormat), "set format") &&
|
||||
/* set channels (implicitly sets frame bits) */
|
||||
ok(psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(pDevice->Format)), "set channels") &&
|
||||
/* set rate (implicitly constrains period/buffer parameters) */
|
||||
ok(psnd_pcm_hw_params_set_rate(data->pcmHandle, p, frequency, 0), "set rate") &&
|
||||
/* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
|
||||
ok(psnd_pcm_hw_params_set_buffer_size_min(data->pcmHandle, p, &bufferSizeInFrames), "set buffer size min") &&
|
||||
/* install and prepare hardware configuration */
|
||||
ok(psnd_pcm_hw_params(data->pcmHandle, p), "set params")))
|
||||
|
||||
if(!allowmmap)
|
||||
err = "no mmap";
|
||||
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_MMAP_INTERLEAVED)) < 0)
|
||||
{
|
||||
if(i < 0)
|
||||
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
|
||||
bufferSizeInFrames = SampleSize;
|
||||
if(!(ok(psnd_pcm_hw_params_any(data->pcmHandle, p), "any") &&
|
||||
ok(psnd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED), "set access") &&
|
||||
ok(psnd_pcm_hw_params_set_format(data->pcmHandle, p, alsaFormat), "set format") &&
|
||||
ok(psnd_pcm_hw_params_set_channels(data->pcmHandle, p, aluChannelsFromFormat(pDevice->Format)), "set channels") &&
|
||||
ok(psnd_pcm_hw_params_set_rate(data->pcmHandle, p, frequency, 0), "set rate") &&
|
||||
ok(psnd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames), "set buffer size near") &&
|
||||
ok(psnd_pcm_hw_params(data->pcmHandle, p), "set params")))
|
||||
{
|
||||
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
|
||||
psnd_pcm_hw_params_free(p);
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
err = "set access";
|
||||
allowmmap = 0;
|
||||
}
|
||||
/* set format (implicitly sets sample bits) */
|
||||
if(err == NULL && (i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, data->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)
|
||||
err = "set channels";
|
||||
/* set rate (implicitly constrains period/buffer parameters) */
|
||||
if(err == NULL && (i=psnd_pcm_hw_params_set_rate(data->pcmHandle, p, 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_min(data->pcmHandle, p, &bufferSizeInFrames)) < 0)
|
||||
{
|
||||
err = "set buffer size min";
|
||||
allowmmap = 0;
|
||||
}
|
||||
/* install and prepare hardware configuration */
|
||||
if(err == NULL && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0)
|
||||
err = "set params";
|
||||
if(!allowmmap)
|
||||
{
|
||||
err = NULL;
|
||||
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_MMAP_INTERLEAVED)) < 0)
|
||||
err = "set access";
|
||||
/* set format (implicitly sets sample bits) */
|
||||
if(err == NULL && (i=psnd_pcm_hw_params_set_format(data->pcmHandle, p, data->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)
|
||||
err = "set channels";
|
||||
/* set rate (implicitly constrains period/buffer parameters) */
|
||||
if(err == NULL && (i=psnd_pcm_hw_params_set_rate(data->pcmHandle, p, 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)
|
||||
err = "set buffer size near";
|
||||
/* install and prepare hardware configuration */
|
||||
if(err == NULL && (i=psnd_pcm_hw_params(data->pcmHandle, p)) < 0)
|
||||
err = "set params";
|
||||
}
|
||||
if(err != NULL)
|
||||
{
|
||||
AL_PRINT("%s failed: %s\n", err, psnd_strerror(i));
|
||||
psnd_pcm_hw_params_free(p);
|
||||
psnd_pcm_close(data->pcmHandle);
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
#undef ok
|
||||
|
||||
if((i=psnd_pcm_hw_params_get_access(p, &access)) < 0)
|
||||
{
|
||||
@@ -901,7 +948,7 @@ void alc_alsa_init(BackendFuncs *func_list)
|
||||
} while(0)
|
||||
#else
|
||||
str = NULL;
|
||||
alsa_handle = 0xDEADBEEF;
|
||||
alsa_handle = (void*)0xDEADBEEF;
|
||||
#define LOAD_FUNC(f) p##f = f
|
||||
#endif
|
||||
|
||||
@@ -925,6 +972,11 @@ LOAD_FUNC(snd_pcm_hw_params_get_buffer_size);
|
||||
LOAD_FUNC(snd_pcm_hw_params_get_period_size);
|
||||
LOAD_FUNC(snd_pcm_hw_params_get_access);
|
||||
LOAD_FUNC(snd_pcm_hw_params);
|
||||
LOAD_FUNC(snd_pcm_sw_params_malloc);
|
||||
LOAD_FUNC(snd_pcm_sw_params_current);
|
||||
LOAD_FUNC(snd_pcm_sw_params_set_avail_min);
|
||||
LOAD_FUNC(snd_pcm_sw_params);
|
||||
LOAD_FUNC(snd_pcm_sw_params_free);
|
||||
LOAD_FUNC(snd_pcm_prepare);
|
||||
LOAD_FUNC(snd_pcm_start);
|
||||
LOAD_FUNC(snd_pcm_resume);
|
||||
@@ -962,15 +1014,11 @@ LOAD_FUNC(snd_card_next);
|
||||
card = -1;
|
||||
if(psnd_card_next(&card) < 0 || card < 0)
|
||||
AL_PRINT("no playback cards found...\n");
|
||||
else
|
||||
{
|
||||
alsaDeviceList[0] = AppendDeviceList("ALSA Software on default");
|
||||
allDevNameMap[0].name = AppendAllDeviceList("ALSA Software on default");
|
||||
}
|
||||
|
||||
alsaDevice = AppendDeviceList("ALSA Software");
|
||||
allDevNameMap[0].name = AppendAllDeviceList("ALSA Software on default");
|
||||
|
||||
while (card >= 0) {
|
||||
int firstDev = 1;
|
||||
|
||||
sprintf(name, "hw:%d", card);
|
||||
if ((err = psnd_ctl_open(&handle, name, 0)) < 0) {
|
||||
AL_PRINT("control open (%i): %s\n", card, psnd_strerror(err));
|
||||
@@ -991,13 +1039,6 @@ LOAD_FUNC(snd_card_next);
|
||||
if (dev < 0)
|
||||
break;
|
||||
|
||||
if(firstDev && card < MAX_DEVICES-1) {
|
||||
firstDev = 0;
|
||||
snprintf(name, sizeof(name), "ALSA Software on %s",
|
||||
psnd_ctl_card_info_get_name(info));
|
||||
alsaDeviceList[card+1] = AppendDeviceList(name);
|
||||
}
|
||||
|
||||
psnd_pcm_info_set_device(pcminfo, dev);
|
||||
psnd_pcm_info_set_subdevice(pcminfo, 0);
|
||||
psnd_pcm_info_set_stream(pcminfo, stream);
|
||||
@@ -1009,8 +1050,8 @@ LOAD_FUNC(snd_card_next);
|
||||
|
||||
cname = psnd_ctl_card_info_get_name(info);
|
||||
dname = psnd_pcm_info_get_name(pcminfo);
|
||||
snprintf(name, sizeof(name), "ALSA Software on %s [%s]",
|
||||
cname, dname);
|
||||
snprintf(name, sizeof(name), "ALSA Software on %s [%s] (hw:%d,%d)",
|
||||
cname, dname, card, dev);
|
||||
allDevNameMap[idx].name = AppendAllDeviceList(name);
|
||||
allDevNameMap[idx].card = card;
|
||||
allDevNameMap[idx].dev = dev;
|
||||
@@ -1068,8 +1109,8 @@ next_card:
|
||||
|
||||
cname = psnd_ctl_card_info_get_name(info);
|
||||
dname = psnd_pcm_info_get_name(pcminfo);
|
||||
snprintf(name, sizeof(name), "ALSA Capture on %s [%s]",
|
||||
cname, dname);
|
||||
snprintf(name, sizeof(name), "ALSA Capture on %s [%s] (hw:%d,%d)",
|
||||
cname, dname, card, dev);
|
||||
allCaptureDevNameMap[idx].name = AppendCaptureDeviceList(name);
|
||||
allCaptureDevNameMap[idx].card = card;
|
||||
allCaptureDevNameMap[idx].dev = dev;
|
||||
|
||||
+79
-26
@@ -28,17 +28,28 @@
|
||||
|
||||
#include <dsound.h>
|
||||
#include <mmreg.h>
|
||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||
#include <ks.h>
|
||||
#include <ksmedia.h>
|
||||
#endif
|
||||
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
|
||||
#ifndef DSSPEAKER_5POINT1
|
||||
#define DSSPEAKER_5POINT1 6
|
||||
#endif
|
||||
#ifndef DSSPEAKER_7POINT1
|
||||
#define DSSPEAKER_7POINT1 7
|
||||
#endif
|
||||
|
||||
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||
|
||||
static void *ds_handle;
|
||||
static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter);
|
||||
static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext);
|
||||
|
||||
// Since DSound doesn't report the fragment size, emulate it
|
||||
static int num_frags;
|
||||
|
||||
@@ -64,29 +75,38 @@ static ALuint DSoundProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||
DSoundData *pData = (DSoundData*)pDevice->ExtraData;
|
||||
DSBCAPS DSBCaps;
|
||||
DWORD LastCursor = 0;
|
||||
DWORD PlayCursor;
|
||||
VOID *WritePtr1, *WritePtr2;
|
||||
DWORD WriteCnt1, WriteCnt2;
|
||||
DWORD BufferSize;
|
||||
DWORD FragSize;
|
||||
DWORD avail;
|
||||
HRESULT err;
|
||||
|
||||
BufferSize = pDevice->UpdateSize * num_frags *
|
||||
aluBytesFromFormat(pDevice->Format) *
|
||||
aluChannelsFromFormat(pDevice->Format);
|
||||
memset(&DSBCaps, 0, sizeof(DSBCaps));
|
||||
DSBCaps.dwSize = sizeof(DSBCaps);
|
||||
err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps);
|
||||
if(FAILED(err))
|
||||
{
|
||||
AL_PRINT("Failed to get buffer caps: 0x%lx\n", err);
|
||||
return 1;
|
||||
}
|
||||
FragSize = DSBCaps.dwBufferBytes / num_frags;
|
||||
|
||||
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL);
|
||||
while(!pData->killNow)
|
||||
{
|
||||
// Get current play and write cursors
|
||||
IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
|
||||
avail = (PlayCursor-LastCursor+BufferSize) % BufferSize;
|
||||
avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;
|
||||
|
||||
if(avail < BufferSize/num_frags)
|
||||
if(avail < FragSize)
|
||||
{
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
avail -= avail%FragSize;
|
||||
|
||||
// Lock output buffer
|
||||
WriteCnt1 = 0;
|
||||
@@ -120,7 +140,7 @@ static ALuint DSoundProc(ALvoid *ptr)
|
||||
|
||||
// Update old write cursor location
|
||||
LastCursor += WriteCnt1+WriteCnt2;
|
||||
LastCursor %= BufferSize;
|
||||
LastCursor %= DSBCaps.dwBufferBytes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -133,9 +153,13 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
WAVEFORMATEXTENSIBLE OutputType;
|
||||
DWORD frameSize = 0;
|
||||
LPGUID guid = NULL;
|
||||
ALenum format = 0;
|
||||
DWORD speakers;
|
||||
HRESULT hr;
|
||||
|
||||
if(ds_handle == NULL)
|
||||
return ALC_FALSE;
|
||||
|
||||
if(deviceName)
|
||||
{
|
||||
int i;
|
||||
@@ -167,7 +191,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
}
|
||||
|
||||
//DirectSound Init code
|
||||
hr = DirectSoundCreate(guid, &pData->lpDS, NULL);
|
||||
hr = pDirectSoundCreate(guid, &pData->lpDS, NULL);
|
||||
if(SUCCEEDED(hr))
|
||||
hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY);
|
||||
|
||||
@@ -197,23 +221,23 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
if(speakers == DSSPEAKER_MONO)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
device->Format = AL_FORMAT_MONO8;
|
||||
format = AL_FORMAT_MONO8;
|
||||
else
|
||||
device->Format = AL_FORMAT_MONO16;
|
||||
format = AL_FORMAT_MONO16;
|
||||
}
|
||||
else if(speakers == DSSPEAKER_STEREO)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
device->Format = AL_FORMAT_STEREO8;
|
||||
format = AL_FORMAT_STEREO8;
|
||||
else
|
||||
device->Format = AL_FORMAT_STEREO16;
|
||||
format = AL_FORMAT_STEREO16;
|
||||
}
|
||||
else if(speakers == DSSPEAKER_QUAD)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
device->Format = AL_FORMAT_QUAD8;
|
||||
format = AL_FORMAT_QUAD8;
|
||||
else
|
||||
device->Format = AL_FORMAT_QUAD16;
|
||||
format = AL_FORMAT_QUAD16;
|
||||
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||
SPEAKER_FRONT_RIGHT |
|
||||
SPEAKER_BACK_LEFT |
|
||||
@@ -222,9 +246,9 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
else if(speakers == DSSPEAKER_5POINT1)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
device->Format = AL_FORMAT_51CHN8;
|
||||
format = AL_FORMAT_51CHN8;
|
||||
else
|
||||
device->Format = AL_FORMAT_51CHN16;
|
||||
format = AL_FORMAT_51CHN16;
|
||||
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||
SPEAKER_FRONT_RIGHT |
|
||||
SPEAKER_FRONT_CENTER |
|
||||
@@ -235,9 +259,9 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
else if(speakers == DSSPEAKER_7POINT1)
|
||||
{
|
||||
if(aluBytesFromFormat(device->Format) == 1)
|
||||
device->Format = AL_FORMAT_71CHN8;
|
||||
format = AL_FORMAT_71CHN8;
|
||||
else
|
||||
device->Format = AL_FORMAT_71CHN16;
|
||||
format = AL_FORMAT_71CHN16;
|
||||
OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
|
||||
SPEAKER_FRONT_RIGHT |
|
||||
SPEAKER_FRONT_CENTER |
|
||||
@@ -247,18 +271,17 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
SPEAKER_SIDE_LEFT |
|
||||
SPEAKER_SIDE_RIGHT;
|
||||
}
|
||||
frameSize = aluBytesFromFormat(device->Format) *
|
||||
aluChannelsFromFormat(device->Format);
|
||||
else
|
||||
format = device->Format;
|
||||
frameSize = aluBytesFromFormat(format) * aluChannelsFromFormat(format);
|
||||
|
||||
OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
OutputType.Format.nChannels = aluChannelsFromFormat(device->Format);
|
||||
OutputType.Format.wBitsPerSample = aluBytesFromFormat(device->Format) * 8;
|
||||
OutputType.Format.nChannels = aluChannelsFromFormat(format);
|
||||
OutputType.Format.wBitsPerSample = aluBytesFromFormat(format) * 8;
|
||||
OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8;
|
||||
OutputType.Format.nSamplesPerSec = device->Frequency;
|
||||
OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign;
|
||||
OutputType.Format.cbSize = 0;
|
||||
|
||||
device->UpdateSize /= num_frags;
|
||||
}
|
||||
|
||||
if(OutputType.Format.nChannels > 2)
|
||||
@@ -286,7 +309,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
|
||||
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
|
||||
DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
|
||||
DSBDescription.dwBufferBytes=device->UpdateSize * num_frags * frameSize;
|
||||
DSBDescription.dwBufferBytes=(device->UpdateSize/num_frags) * num_frags * frameSize;
|
||||
DSBDescription.lpwfxFormat=&OutputType.Format;
|
||||
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
|
||||
}
|
||||
@@ -315,6 +338,9 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->Format = format;
|
||||
device->UpdateSize /= num_frags;
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
@@ -411,10 +437,37 @@ void alcDSoundInit(BackendFuncs *FuncList)
|
||||
|
||||
*FuncList = DSoundFuncs;
|
||||
|
||||
#ifdef _WIN32
|
||||
ds_handle = LoadLibraryA("dsound.dll");
|
||||
if(ds_handle == NULL)
|
||||
{
|
||||
AL_PRINT("Failed to load dsound.dll\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#define LOAD_FUNC(f) do { \
|
||||
p##f = (void*)GetProcAddress((HMODULE)ds_handle, #f); \
|
||||
if(p##f == NULL) \
|
||||
{ \
|
||||
FreeLibrary(ds_handle); \
|
||||
ds_handle = NULL; \
|
||||
AL_PRINT("Could not load %s from dsound.dll\n", #f); \
|
||||
return; \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
ds_handle = (void*)0xDEADBEEF;
|
||||
#define LOAD_FUNC(f) p##f = f
|
||||
#endif
|
||||
|
||||
LOAD_FUNC(DirectSoundCreate);
|
||||
LOAD_FUNC(DirectSoundEnumerateA);
|
||||
#undef LOAD_FUNC
|
||||
|
||||
num_frags = GetConfigValueInt("dsound", "periods", 4);
|
||||
if(num_frags < 2) num_frags = 2;
|
||||
|
||||
hr = DirectSoundEnumerate(DSoundEnumDevices, &iter);
|
||||
hr = pDirectSoundEnumerateA(DSoundEnumDevices, &iter);
|
||||
if(FAILED(hr))
|
||||
AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
|
||||
}
|
||||
|
||||
@@ -79,35 +79,35 @@ static ALuint OSSProc(ALvoid *ptr)
|
||||
{
|
||||
ALCdevice *pDevice = (ALCdevice*)ptr;
|
||||
oss_data *data = (oss_data*)pDevice->ExtraData;
|
||||
int remaining = 0;
|
||||
int wrote;
|
||||
|
||||
while(!data->killNow)
|
||||
{
|
||||
int len = data->data_size - remaining;
|
||||
ALint len = data->data_size;
|
||||
ALubyte *WritePtr = data->mix_data;
|
||||
|
||||
if(len > 0)
|
||||
{
|
||||
SuspendContext(NULL);
|
||||
aluMixData(pDevice->Context, data->mix_data+remaining, len, pDevice->Format);
|
||||
ProcessContext(NULL);
|
||||
}
|
||||
SuspendContext(NULL);
|
||||
aluMixData(pDevice->Context, WritePtr, len, pDevice->Format);
|
||||
ProcessContext(NULL);
|
||||
|
||||
remaining += len;
|
||||
wrote = write(data->fd, data->mix_data, remaining);
|
||||
if(wrote < 0)
|
||||
while(len > 0 && !data->killNow)
|
||||
{
|
||||
AL_PRINT("write failed: %s\n", strerror(errno));
|
||||
remaining = 0;
|
||||
wrote = write(data->fd, WritePtr, len);
|
||||
if(wrote < 0)
|
||||
{
|
||||
if(errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
{
|
||||
AL_PRINT("write failed: %s\n", strerror(errno));
|
||||
len = 0;
|
||||
}
|
||||
else
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
len -= wrote;
|
||||
WritePtr += wrote;
|
||||
}
|
||||
else if(wrote > 0)
|
||||
{
|
||||
remaining -= wrote;
|
||||
if(remaining > 0)
|
||||
memmove(data->mix_data, data->mix_data+wrote, remaining);
|
||||
}
|
||||
else
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -221,8 +221,6 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
|
||||
}
|
||||
#undef ok
|
||||
|
||||
device->Frequency = ossSpeed;
|
||||
|
||||
if((int)aluChannelsFromFormat(device->Format) != numChannels)
|
||||
{
|
||||
AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), numChannels);
|
||||
@@ -240,8 +238,6 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->UpdateSize = info.fragsize / frameSize;
|
||||
|
||||
data->data_size = device->UpdateSize * frameSize;
|
||||
data->mix_data = calloc(1, data->data_size);
|
||||
|
||||
@@ -255,6 +251,9 @@ static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->Frequency = ossSpeed;
|
||||
device->UpdateSize = info.fragsize / frameSize;
|
||||
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 1999-2007 by authors.
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "alMain.h"
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <portaudio.h>
|
||||
|
||||
static void *pa_handle;
|
||||
#define MAKE_FUNC(x) static typeof(x) * p##x
|
||||
MAKE_FUNC(Pa_Initialize);
|
||||
MAKE_FUNC(Pa_GetErrorText);
|
||||
MAKE_FUNC(Pa_StartStream);
|
||||
MAKE_FUNC(Pa_StopStream);
|
||||
MAKE_FUNC(Pa_OpenStream);
|
||||
MAKE_FUNC(Pa_CloseStream);
|
||||
MAKE_FUNC(Pa_GetDefaultOutputDevice);
|
||||
#undef MAKE_FUNC
|
||||
|
||||
|
||||
static char *pa_device;
|
||||
|
||||
typedef struct {
|
||||
PaStream *stream;
|
||||
} pa_data;
|
||||
|
||||
|
||||
static int pa_callback(const void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
|
||||
const PaStreamCallbackFlags statusFlags, void *userData)
|
||||
{
|
||||
ALCdevice *device = (ALCdevice*)userData;
|
||||
int frameSize;
|
||||
|
||||
(void)inputBuffer;
|
||||
(void)timeInfo;
|
||||
(void)statusFlags;
|
||||
|
||||
frameSize = aluBytesFromFormat(device->Format);
|
||||
frameSize *= aluChannelsFromFormat(device->Format);
|
||||
|
||||
SuspendContext(NULL);
|
||||
aluMixData(device->Context, outputBuffer, framesPerBuffer*frameSize, device->Format);
|
||||
ProcessContext(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
|
||||
{
|
||||
PaStreamParameters outParams;
|
||||
pa_data *data;
|
||||
int periods;
|
||||
PaError err;
|
||||
|
||||
if(pa_handle == NULL)
|
||||
return ALC_FALSE;
|
||||
|
||||
if(deviceName)
|
||||
{
|
||||
if(strcmp(deviceName, pa_device) != 0)
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->szDeviceName = pa_device;
|
||||
|
||||
data = (pa_data*)calloc(1, sizeof(pa_data));
|
||||
device->ExtraData = data;
|
||||
|
||||
outParams.device = GetConfigValueInt("port", "device", -1);
|
||||
if(outParams.device < 0)
|
||||
outParams.device = pPa_GetDefaultOutputDevice();
|
||||
outParams.suggestedLatency = (float)device->UpdateSize /
|
||||
(float)device->Frequency;
|
||||
outParams.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
switch(aluBytesFromFormat(device->Format))
|
||||
{
|
||||
case 1:
|
||||
outParams.sampleFormat = paUInt8;
|
||||
break;
|
||||
case 2:
|
||||
outParams.sampleFormat = paInt16;
|
||||
break;
|
||||
default:
|
||||
outParams.sampleFormat = -1;
|
||||
AL_PRINT("Unknown format?! %x\n", device->Format);
|
||||
}
|
||||
|
||||
periods = GetConfigValueInt("port", "periods", 4);
|
||||
if((int)periods <= 0)
|
||||
periods = 4;
|
||||
outParams.channelCount = aluChannelsFromFormat(device->Format);
|
||||
|
||||
err = pPa_OpenStream(&data->stream, NULL, &outParams, device->Frequency,
|
||||
device->UpdateSize/periods, paNoFlag,
|
||||
pa_callback, device);
|
||||
if(err != paNoError)
|
||||
{
|
||||
AL_PRINT("Pa_OpenStream() returned an error: %s\n", pPa_GetErrorText(err));
|
||||
device->ExtraData = NULL;
|
||||
free(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->UpdateSize /= periods;
|
||||
return ALC_TRUE;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
free(data);
|
||||
device->ExtraData = NULL;
|
||||
}
|
||||
|
||||
|
||||
static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
|
||||
{
|
||||
return ALC_FALSE;
|
||||
(void)device;
|
||||
(void)deviceName;
|
||||
(void)frequency;
|
||||
(void)format;
|
||||
(void)SampleSize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const BackendFuncs pa_funcs = {
|
||||
pa_open_playback,
|
||||
pa_close_playback,
|
||||
pa_open_capture,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
void alc_pa_init(BackendFuncs *func_list)
|
||||
{
|
||||
const char *str;
|
||||
PaError err;
|
||||
|
||||
*func_list = pa_funcs;
|
||||
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
# define PALIB "libportaudio.2.dylib"
|
||||
#else
|
||||
# define PALIB "libportaudio.so.2"
|
||||
#endif
|
||||
pa_handle = dlopen(PALIB, RTLD_NOW);
|
||||
if(!pa_handle)
|
||||
return;
|
||||
dlerror();
|
||||
|
||||
#define LOAD_FUNC(f) do { \
|
||||
p##f = (typeof(f)*)dlsym(pa_handle, #f); \
|
||||
if((str=dlerror()) != NULL) \
|
||||
{ \
|
||||
dlclose(pa_handle); \
|
||||
pa_handle = NULL; \
|
||||
AL_PRINT("Could not load %s from "PALIB": %s\n", #f, str); \
|
||||
return; \
|
||||
} \
|
||||
} while(0)
|
||||
#else
|
||||
str = NULL;
|
||||
pa_handle = (void*)0xDEADBEEF;
|
||||
#define LOAD_FUNC(f) p##f = f
|
||||
#endif
|
||||
|
||||
LOAD_FUNC(Pa_Initialize);
|
||||
LOAD_FUNC(Pa_GetErrorText);
|
||||
LOAD_FUNC(Pa_StartStream);
|
||||
LOAD_FUNC(Pa_StopStream);
|
||||
LOAD_FUNC(Pa_OpenStream);
|
||||
LOAD_FUNC(Pa_CloseStream);
|
||||
LOAD_FUNC(Pa_GetDefaultOutputDevice);
|
||||
#undef LOAD_FUNC
|
||||
|
||||
if((err=pPa_Initialize()) != paNoError)
|
||||
{
|
||||
AL_PRINT("Pa_Initialize() returned an error: %s\n", pPa_GetErrorText(err));
|
||||
return;
|
||||
}
|
||||
|
||||
pa_device = AppendDeviceList("PortAudio Software");
|
||||
AppendAllDeviceList(pa_device);
|
||||
}
|
||||
@@ -0,0 +1,595 @@
|
||||
/**
|
||||
* OpenAL cross platform audio library
|
||||
* Copyright (C) 2009 by Konstantinos Natsakis <konstantinos.natsakis@gmail.com>
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "alMain.h"
|
||||
#ifdef HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
#if PA_API_VERSION == 11
|
||||
#define PA_STREAM_ADJUST_LATENCY 0x2000U
|
||||
static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x)
|
||||
{
|
||||
return (x == PA_STREAM_CREATING || x == PA_STREAM_READY);
|
||||
}
|
||||
static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x)
|
||||
{
|
||||
return (x == PA_CONTEXT_CONNECTING || x == PA_CONTEXT_AUTHORIZING ||
|
||||
x == PA_CONTEXT_SETTING_NAME || x == PA_CONTEXT_READY);
|
||||
}
|
||||
#define PA_STREAM_IS_GOOD PA_STREAM_IS_GOOD
|
||||
#define PA_CONTEXT_IS_GOOD PA_CONTEXT_IS_GOOD
|
||||
#elif PA_API_VERSION != 12
|
||||
#error Invalid PulseAudio API version
|
||||
#endif
|
||||
|
||||
static void *pa_handle;
|
||||
#define MAKE_FUNC(x) static typeof(x) * p##x
|
||||
MAKE_FUNC(pa_context_unref);
|
||||
MAKE_FUNC(pa_sample_spec_valid);
|
||||
MAKE_FUNC(pa_stream_drop);
|
||||
MAKE_FUNC(pa_strerror);
|
||||
MAKE_FUNC(pa_context_get_state);
|
||||
MAKE_FUNC(pa_stream_get_state);
|
||||
MAKE_FUNC(pa_threaded_mainloop_signal);
|
||||
MAKE_FUNC(pa_stream_peek);
|
||||
MAKE_FUNC(pa_threaded_mainloop_wait);
|
||||
MAKE_FUNC(pa_threaded_mainloop_unlock);
|
||||
MAKE_FUNC(pa_context_new);
|
||||
MAKE_FUNC(pa_threaded_mainloop_stop);
|
||||
MAKE_FUNC(pa_context_disconnect);
|
||||
MAKE_FUNC(pa_threaded_mainloop_start);
|
||||
MAKE_FUNC(pa_threaded_mainloop_get_api);
|
||||
MAKE_FUNC(pa_context_set_state_callback);
|
||||
MAKE_FUNC(pa_stream_write);
|
||||
MAKE_FUNC(pa_xfree);
|
||||
MAKE_FUNC(pa_stream_connect_record);
|
||||
MAKE_FUNC(pa_stream_connect_playback);
|
||||
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_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_read_callback);
|
||||
MAKE_FUNC(pa_stream_set_state_callback);
|
||||
MAKE_FUNC(pa_stream_new);
|
||||
MAKE_FUNC(pa_stream_disconnect);
|
||||
MAKE_FUNC(pa_threaded_mainloop_lock);
|
||||
#undef MAKE_FUNC
|
||||
|
||||
typedef struct {
|
||||
ALCdevice *device;
|
||||
|
||||
ALCenum format;
|
||||
ALCuint samples;
|
||||
ALCuint frequency;
|
||||
ALCuint frame_size;
|
||||
|
||||
RingBuffer *ring;
|
||||
|
||||
pa_buffer_attr attr;
|
||||
pa_sample_spec spec;
|
||||
|
||||
char path_name[PATH_MAX];
|
||||
const char *context_name;
|
||||
const char *stream_name;
|
||||
|
||||
pa_threaded_mainloop *loop;
|
||||
|
||||
pa_stream *stream;
|
||||
pa_context *context;
|
||||
} pulse_data;
|
||||
|
||||
static char *pulse_device;
|
||||
static char *pulse_capture_device;
|
||||
|
||||
// PulseAudio Event Callbacks {{{
|
||||
static void stream_state_callback(pa_stream *stream, void *pdata) //{{{
|
||||
{
|
||||
pulse_data *data = pdata;
|
||||
|
||||
switch(ppa_stream_get_state(stream))
|
||||
{
|
||||
case PA_STREAM_READY:
|
||||
AL_PRINT("%s: %s ready!\n", data->context_name, data->stream_name);
|
||||
break;
|
||||
|
||||
case PA_STREAM_FAILED:
|
||||
AL_PRINT("%s: %s: Connection failed: %s\n", data->context_name,
|
||||
data->stream_name, ppa_strerror(ppa_context_errno(data->context)));
|
||||
break;
|
||||
|
||||
case PA_STREAM_TERMINATED:
|
||||
AL_PRINT("%s: %s terminated!\n", data->context_name, data->stream_name);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ppa_threaded_mainloop_signal(data->loop, 1);
|
||||
} //}}}
|
||||
|
||||
static void context_state_callback(pa_context *context, void *pdata) //{{{
|
||||
{
|
||||
pulse_data *data = pdata;
|
||||
|
||||
switch(ppa_context_get_state(context))
|
||||
{
|
||||
case PA_CONTEXT_READY:
|
||||
AL_PRINT("%s ready!\n", data->context_name);
|
||||
break;
|
||||
|
||||
case PA_CONTEXT_FAILED:
|
||||
AL_PRINT("%s: Connection failed: %s\n", data->context_name,
|
||||
ppa_strerror(ppa_context_errno(context)));
|
||||
break;
|
||||
|
||||
case PA_CONTEXT_TERMINATED:
|
||||
AL_PRINT("%s terminated!\n", data->context_name);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ppa_threaded_mainloop_signal(data->loop, 1);
|
||||
} //}}}
|
||||
//}}}
|
||||
|
||||
// PulseAudio I/O Callbacks //{{{
|
||||
static void stream_write_callback(pa_stream *stream, size_t len, void *pdata) //{{{
|
||||
{
|
||||
ALCdevice *Device = pdata;
|
||||
void *buf = ppa_xmalloc0(len);
|
||||
|
||||
SuspendContext(NULL);
|
||||
aluMixData(Device->Context, buf, len, Device->Format);
|
||||
ProcessContext(NULL);
|
||||
|
||||
ppa_stream_write(stream, buf, len, ppa_xfree, 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, ALCchar *device_name, ALCenum format, ALCuint samples, ALCuint frequency) //{{{
|
||||
{
|
||||
pulse_data *data = ppa_xmalloc0(sizeof(pulse_data));
|
||||
|
||||
data->device = device;
|
||||
data->format = format;
|
||||
data->samples = samples;
|
||||
data->frequency = frequency;
|
||||
data->frame_size = aluBytesFromFormat(format) * aluChannelsFromFormat(format);
|
||||
|
||||
if(ppa_get_binary_name(data->path_name, sizeof(data->path_name)))
|
||||
data->context_name = ppa_path_get_filename(data->path_name);
|
||||
else
|
||||
data->context_name = "OpenAL Soft";
|
||||
|
||||
if(!(data->ring = CreateRingBuffer(data->frame_size, data->samples)))
|
||||
{
|
||||
ppa_xfree(data);
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
device->ExtraData = data;
|
||||
device->szDeviceName = device_name;
|
||||
|
||||
data->attr.minreq = -1;
|
||||
data->attr.prebuf = -1;
|
||||
data->attr.maxlength = -1;
|
||||
|
||||
if(device->IsCaptureDevice)
|
||||
{
|
||||
data->attr.tlength = -1;
|
||||
data->attr.fragsize = data->frame_size * data->samples / 2;
|
||||
data->stream_name = "Capture Stream";
|
||||
}
|
||||
else
|
||||
{
|
||||
data->attr.tlength = data->frame_size * (device->UpdateSize&~3);
|
||||
data->attr.fragsize = -1;
|
||||
data->stream_name = "Playback Stream";
|
||||
}
|
||||
|
||||
data->spec.rate = data->frequency;
|
||||
data->spec.channels = aluChannelsFromFormat(data->format);
|
||||
|
||||
switch(aluBytesFromFormat(data->format))
|
||||
{
|
||||
case 1:
|
||||
data->spec.format = PA_SAMPLE_U8;
|
||||
break;
|
||||
case 2:
|
||||
data->spec.format = PA_SAMPLE_S16NE;
|
||||
break;
|
||||
default:
|
||||
AL_PRINT("Unknown format: %x\n", data->format);
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if(ppa_sample_spec_valid(&data->spec) == 0)
|
||||
{
|
||||
AL_PRINT("Invalid sample format\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if(!(data->loop = ppa_threaded_mainloop_new()))
|
||||
{
|
||||
AL_PRINT("pa_threaded_mainloop_new() failed!\n");
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if(ppa_threaded_mainloop_start(data->loop) < 0)
|
||||
{
|
||||
AL_PRINT("pa_threaded_mainloop_start() failed\n");
|
||||
goto out3;
|
||||
}
|
||||
|
||||
ppa_threaded_mainloop_lock(data->loop);
|
||||
|
||||
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)));
|
||||
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
goto out3;
|
||||
}
|
||||
|
||||
ppa_context_set_state_callback(data->context, context_state_callback, data);
|
||||
|
||||
if(ppa_context_connect(data->context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0)
|
||||
{
|
||||
AL_PRINT("Context did not connect: %s\n",
|
||||
ppa_strerror(ppa_context_errno(data->context)));
|
||||
|
||||
ppa_context_unref(data->context);
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
|
||||
data->context = NULL;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
while(ppa_context_get_state(data->context) != PA_CONTEXT_READY)
|
||||
{
|
||||
if(!PA_CONTEXT_IS_GOOD(ppa_context_get_state(data->context)))
|
||||
{
|
||||
ppa_context_unref(data->context);
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
|
||||
data->context = NULL;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
ppa_threaded_mainloop_wait(data->loop);
|
||||
ppa_threaded_mainloop_accept(data->loop);
|
||||
}
|
||||
|
||||
data->stream = ppa_stream_new(data->context, data->stream_name, &data->spec, NULL);
|
||||
if(!data->stream)
|
||||
{
|
||||
AL_PRINT("pa_stream_new() failed: %s\n",
|
||||
ppa_strerror(ppa_context_errno(data->context)));
|
||||
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
goto out4;
|
||||
}
|
||||
|
||||
ppa_stream_set_state_callback(data->stream, stream_state_callback, data);
|
||||
|
||||
if(device->IsCaptureDevice)
|
||||
{
|
||||
if(ppa_stream_connect_record(data->stream, NULL, &data->attr, PA_STREAM_ADJUST_LATENCY) < 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;
|
||||
goto out4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
goto out4;
|
||||
}
|
||||
}
|
||||
|
||||
while(ppa_stream_get_state(data->stream) != PA_STREAM_READY)
|
||||
{
|
||||
if(!PA_STREAM_IS_GOOD(ppa_stream_get_state(data->stream)))
|
||||
{
|
||||
ppa_stream_unref(data->stream);
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
|
||||
data->stream = NULL;
|
||||
goto out4;
|
||||
}
|
||||
|
||||
ppa_threaded_mainloop_wait(data->loop);
|
||||
ppa_threaded_mainloop_accept(data->loop);
|
||||
}
|
||||
|
||||
device->UpdateSize /= 4;
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
|
||||
return ALC_TRUE;
|
||||
|
||||
out4:
|
||||
ppa_threaded_mainloop_lock(data->loop);
|
||||
|
||||
ppa_context_disconnect(data->context);
|
||||
ppa_context_unref(data->context);
|
||||
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
out3:
|
||||
ppa_threaded_mainloop_stop(data->loop);
|
||||
ppa_threaded_mainloop_free(data->loop);
|
||||
out2:
|
||||
device->ExtraData = NULL;
|
||||
device->szDeviceName = NULL;
|
||||
DestroyRingBuffer(data->ring);
|
||||
|
||||
ppa_xfree(data);
|
||||
return ALC_FALSE;
|
||||
} //}}}
|
||||
|
||||
static void pulse_close(ALCdevice *device) //{{{
|
||||
{
|
||||
pulse_data *data = device->ExtraData;
|
||||
|
||||
ppa_threaded_mainloop_lock(data->loop);
|
||||
|
||||
ppa_stream_disconnect(data->stream);
|
||||
ppa_stream_unref(data->stream);
|
||||
|
||||
ppa_context_disconnect(data->context);
|
||||
ppa_context_unref(data->context);
|
||||
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
|
||||
ppa_threaded_mainloop_stop(data->loop);
|
||||
ppa_threaded_mainloop_free(data->loop);
|
||||
|
||||
device->ExtraData = NULL;
|
||||
device->szDeviceName = NULL;
|
||||
DestroyRingBuffer(data->ring);
|
||||
|
||||
ppa_xfree(data);
|
||||
} //}}}
|
||||
//}}}
|
||||
|
||||
// OpenAL {{{
|
||||
static ALCboolean pulse_open_playback(ALCdevice *device, const ALCchar *device_name) //{{{
|
||||
{
|
||||
if(!pa_handle)
|
||||
return ALC_FALSE;
|
||||
|
||||
if(device_name)
|
||||
{
|
||||
if(strcmp(device_name, pulse_device) != 0)
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return pulse_open(device, pulse_device, device->Format, 0, device->Frequency);
|
||||
} //}}}
|
||||
|
||||
static void pulse_close_playback(ALCdevice *device) //{{{
|
||||
{
|
||||
pulse_close(device);
|
||||
} //}}}
|
||||
|
||||
static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_name, ALCuint frequency, ALCenum format, ALCsizei samples) //{{{
|
||||
{
|
||||
if(!pa_handle)
|
||||
return ALC_FALSE;
|
||||
|
||||
if(device_name)
|
||||
{
|
||||
if(strcmp(device_name, pulse_capture_device) != 0)
|
||||
return ALC_FALSE;
|
||||
}
|
||||
|
||||
return pulse_open(device, pulse_capture_device, format, samples, frequency);
|
||||
} //}}}
|
||||
|
||||
static void pulse_close_capture(ALCdevice *device) //{{{
|
||||
{
|
||||
pulse_close(device);
|
||||
} //}}}
|
||||
|
||||
static void pulse_start_capture(ALCdevice *device) //{{{
|
||||
{
|
||||
pulse_data *data = device->ExtraData;
|
||||
|
||||
ppa_threaded_mainloop_lock(data->loop);
|
||||
ppa_stream_set_read_callback(data->stream, stream_read_callback, device);
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
} //}}}
|
||||
|
||||
static void pulse_stop_capture(ALCdevice *device) //{{{
|
||||
{
|
||||
pulse_data *data = device->ExtraData;
|
||||
|
||||
ppa_threaded_mainloop_lock(data->loop);
|
||||
ppa_stream_set_read_callback(data->stream, NULL, NULL);
|
||||
ppa_threaded_mainloop_unlock(data->loop);
|
||||
} //}}}
|
||||
|
||||
static void pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) //{{{
|
||||
{
|
||||
pulse_data *data = device->ExtraData;
|
||||
ALCuint available = RingBufferSize(data->ring);
|
||||
|
||||
if(available < samples)
|
||||
SetALCError(ALC_INVALID_VALUE);
|
||||
else
|
||||
ReadRingBuffer(data->ring, buffer, samples);
|
||||
} //}}}
|
||||
|
||||
static ALCuint pulse_available_samples(ALCdevice *device) //{{{
|
||||
{
|
||||
pulse_data *data = device->ExtraData;
|
||||
return RingBufferSize(data->ring);
|
||||
} //}}}
|
||||
|
||||
BackendFuncs pulse_funcs = { //{{{
|
||||
pulse_open_playback,
|
||||
pulse_close_playback,
|
||||
pulse_open_capture,
|
||||
pulse_close_capture,
|
||||
pulse_start_capture,
|
||||
pulse_stop_capture,
|
||||
pulse_capture_samples,
|
||||
pulse_available_samples
|
||||
}; //}}}
|
||||
|
||||
void alc_pulse_init(BackendFuncs *func_list) //{{{
|
||||
{
|
||||
*func_list = pulse_funcs;
|
||||
|
||||
#ifdef _WIN32
|
||||
pa_handle = LoadLibrary("libpulse-0.dll");
|
||||
#define LOAD_FUNC(x) do { \
|
||||
p##x = GetProcAddress(pa_handle, #x); \
|
||||
if(!(p##x)) { \
|
||||
FreeLibrary(pa_handle); \
|
||||
pa_handle = NULL; \
|
||||
return; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#elif defined (HAVE_DLFCN_H)
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
pa_handle = dlopen("libpulse.0.dylib", RTLD_NOW);
|
||||
#else
|
||||
pa_handle = dlopen("libpulse.so.0", RTLD_NOW);
|
||||
#endif
|
||||
#define LOAD_FUNC(x) do { \
|
||||
p##x = dlsym(pa_handle, #x); \
|
||||
if(!(p##x)) { \
|
||||
dlclose(pa_handle); \
|
||||
pa_handle = NULL; \
|
||||
return; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#else
|
||||
|
||||
pa_handle = (void*)0xDEADBEEF;
|
||||
#define LOAD_FUNC(x) p##x = (x)
|
||||
|
||||
#endif
|
||||
|
||||
LOAD_FUNC(pa_context_unref);
|
||||
LOAD_FUNC(pa_sample_spec_valid);
|
||||
LOAD_FUNC(pa_stream_drop);
|
||||
LOAD_FUNC(pa_strerror);
|
||||
LOAD_FUNC(pa_context_get_state);
|
||||
LOAD_FUNC(pa_stream_get_state);
|
||||
LOAD_FUNC(pa_threaded_mainloop_signal);
|
||||
LOAD_FUNC(pa_stream_peek);
|
||||
LOAD_FUNC(pa_threaded_mainloop_wait);
|
||||
LOAD_FUNC(pa_threaded_mainloop_unlock);
|
||||
LOAD_FUNC(pa_context_new);
|
||||
LOAD_FUNC(pa_threaded_mainloop_stop);
|
||||
LOAD_FUNC(pa_context_disconnect);
|
||||
LOAD_FUNC(pa_threaded_mainloop_start);
|
||||
LOAD_FUNC(pa_threaded_mainloop_get_api);
|
||||
LOAD_FUNC(pa_context_set_state_callback);
|
||||
LOAD_FUNC(pa_stream_write);
|
||||
LOAD_FUNC(pa_xfree);
|
||||
LOAD_FUNC(pa_stream_connect_record);
|
||||
LOAD_FUNC(pa_stream_connect_playback);
|
||||
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_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_read_callback);
|
||||
LOAD_FUNC(pa_stream_set_state_callback);
|
||||
LOAD_FUNC(pa_stream_new);
|
||||
LOAD_FUNC(pa_stream_disconnect);
|
||||
LOAD_FUNC(pa_threaded_mainloop_lock);
|
||||
|
||||
#undef LOAD_FUNC
|
||||
|
||||
pulse_device = AppendDeviceList("PulseAudio Software");
|
||||
AppendAllDeviceList(pulse_device);
|
||||
|
||||
pulse_capture_device = AppendCaptureDeviceList("PulseAudio Capture");
|
||||
} //}}}
|
||||
//}}}
|
||||
+2
-1
@@ -50,6 +50,7 @@ static ALuint WaveProc(ALvoid *ptr)
|
||||
ALuint frameSize;
|
||||
ALuint now, last;
|
||||
size_t WriteCnt;
|
||||
size_t fs;
|
||||
ALuint avail;
|
||||
union {
|
||||
short s;
|
||||
@@ -89,7 +90,7 @@ static ALuint WaveProc(ALvoid *ptr)
|
||||
fputc(bytes[i^1], data->f);
|
||||
}
|
||||
else
|
||||
fwrite(data->buffer, frameSize, WriteCnt, data->f);
|
||||
fs = fwrite(data->buffer, frameSize, WriteCnt, data->f);
|
||||
if(ferror(data->f))
|
||||
{
|
||||
AL_PRINT("Error writing to file\n");
|
||||
|
||||
+100
-31
@@ -10,6 +10,7 @@ INCLUDE(CheckFunctionExists)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
INCLUDE(CheckIncludeFile)
|
||||
INCLUDE(CheckIncludeFiles)
|
||||
INCLUDE(CheckSymbolExists)
|
||||
INCLUDE(CheckCCompilerFlag)
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
INCLUDE(CheckTypeSize)
|
||||
@@ -26,6 +27,8 @@ OPTION(OSS "Check for OSS backend" ON)
|
||||
OPTION(SOLARIS "Check for Solaris backend" ON)
|
||||
OPTION(DSOUND "Check for DirectSound backend" ON)
|
||||
OPTION(WINMM "Check for Windows Multimedia backend" ON)
|
||||
OPTION(PORTAUDIO "Check for PortAudio backend" ON)
|
||||
OPTION(PULSEAUDIO "Check for PulseAudio backend" ON)
|
||||
|
||||
OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON)
|
||||
|
||||
@@ -33,22 +36,22 @@ OPTION(WERROR "Treat compile warnings as errors" OFF)
|
||||
|
||||
OPTION(EXAMPLES "Build example programs" ON)
|
||||
|
||||
OPTION(XCOMPILEWIN32 "Cross-compile to Win32" OFF)
|
||||
OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF)
|
||||
|
||||
|
||||
IF(WIN32 OR XCOMPILEWIN32)
|
||||
SET(LIBNAME openal32)
|
||||
IF(WIN32)
|
||||
SET(LIBNAME OpenAL32)
|
||||
ADD_DEFINITIONS("-D_WIN32")
|
||||
ELSE()
|
||||
SET(LIBNAME openal)
|
||||
ENDIF()
|
||||
|
||||
SET(LIB_MAJOR_VERSION "1")
|
||||
SET(LIB_MINOR_VERSION "6")
|
||||
SET(LIB_BUILD_VERSION "372")
|
||||
SET(LIB_MINOR_VERSION "8")
|
||||
SET(LIB_BUILD_VERSION "466")
|
||||
SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
|
||||
IF(NOT DEFINED LIB_INSTALL_DIR)
|
||||
SET(LIB_INSTALL_DIR "lib")
|
||||
SET(LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
|
||||
ENDIF(NOT DEFINED LIB_INSTALL_DIR)
|
||||
|
||||
|
||||
@@ -66,6 +69,11 @@ IF(NOT CMAKE_BUILD_TYPE)
|
||||
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
ENDIF()
|
||||
IF(NOT CMAKE_DEBUG_POSTFIX)
|
||||
SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING
|
||||
"Library postfix for debug builds. Normally left blank."
|
||||
FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF(MSVC)
|
||||
# ???
|
||||
@@ -73,10 +81,11 @@ IF(MSVC)
|
||||
SET(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DNDEBUG")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-Wall)
|
||||
CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA)
|
||||
IF("${HAVE_W_EXTRA}")
|
||||
IF(HAVE_W_EXTRA)
|
||||
ADD_DEFINITIONS(-Wextra)
|
||||
ENDIF()
|
||||
|
||||
@@ -98,15 +107,15 @@ ELSE()
|
||||
FORCE)
|
||||
|
||||
# Set visibility options if available
|
||||
IF(NOT WIN32 AND NOT XCOMPILEWIN32)
|
||||
IF(NOT WIN32)
|
||||
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
|
||||
int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
|
||||
|
||||
CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_SWITCH)
|
||||
IF("${HAVE_VISIBILITY_SWITCH}")
|
||||
IF(HAVE_VISIBILITY_SWITCH)
|
||||
CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"default\")));
|
||||
int main() {return 0;}" HAVE_GCC_VISIBILITY)
|
||||
IF("${HAVE_GCC_VISIBILITY}")
|
||||
IF(HAVE_GCC_VISIBILITY)
|
||||
ADD_DEFINITIONS(-fvisibility=hidden -DHAVE_GCC_VISIBILITY)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
@@ -118,10 +127,12 @@ CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H)
|
||||
|
||||
CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF)
|
||||
CHECK_LIBRARY_EXISTS(m acosf "" HAVE_ACOSF)
|
||||
CHECK_LIBRARY_EXISTS(m atanf "" HAVE_ATANF)
|
||||
CHECK_LIBRARY_EXISTS(m fabsf "" HAVE_FABSF)
|
||||
IF(HAVE_FENV_H)
|
||||
CHECK_LIBRARY_EXISTS(m fesetround "" HAVE_FESETROUND)
|
||||
ENDIF()
|
||||
IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_FESETROUND)
|
||||
IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_ATANF OR HAVE_FABSF OR HAVE_FESETROUND)
|
||||
SET(EXTRA_LIBS m ${EXTRA_LIBS})
|
||||
ENDIF()
|
||||
CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
|
||||
@@ -157,6 +168,27 @@ IF(NOT HAVE_SNPRINTF)
|
||||
ADD_DEFINITIONS(-Dsnprintf=_snprintf)
|
||||
ENDIF()
|
||||
|
||||
CHECK_FUNCTION_EXISTS(vsnprintf HAVE_VSNPRINTF)
|
||||
IF(NOT HAVE_VSNPRINTF)
|
||||
CHECK_FUNCTION_EXISTS(_vsnprintf HAVE__VSNPRINTF)
|
||||
IF(NOT HAVE__VSNPRINTF)
|
||||
MESSAGE(FATAL_ERROR "No vsnprintf function found, please report!")
|
||||
ENDIF()
|
||||
|
||||
ADD_DEFINITIONS(-Dvsnprintf=_vsnprintf)
|
||||
ENDIF()
|
||||
|
||||
CHECK_SYMBOL_EXISTS(isnan math.h HAVE_ISNAN)
|
||||
IF(NOT HAVE_ISNAN)
|
||||
CHECK_FUNCTION_EXISTS(_isnan HAVE__ISNAN)
|
||||
IF(NOT HAVE__ISNAN)
|
||||
MESSAGE(FATAL_ERROR "No isnan function found, please report!")
|
||||
ENDIF()
|
||||
|
||||
ADD_DEFINITIONS(-Disnan=_isnan)
|
||||
ENDIF()
|
||||
|
||||
|
||||
# Check for the dlopen API (for dynamicly loading backend libs)
|
||||
IF(DLOPEN)
|
||||
CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H)
|
||||
@@ -232,6 +264,7 @@ SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c
|
||||
SET(ALC_OBJS Alc/ALc.c
|
||||
Alc/ALu.c
|
||||
Alc/alcConfig.c
|
||||
Alc/alcEcho.c
|
||||
Alc/alcReverb.c
|
||||
Alc/alcRing.c
|
||||
Alc/alcThread.c
|
||||
@@ -283,16 +316,17 @@ ENDIF()
|
||||
IF(DSOUND)
|
||||
CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H)
|
||||
IF(HAVE_DSOUND_H)
|
||||
SET(HAVE_DSOUND 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/dsound.c)
|
||||
SET(BACKENDS "${BACKENDS} DirectSound,")
|
||||
CHECK_LIBRARY_EXISTS(dsound DirectSoundCreate "" HAVE_LIBDSOUND)
|
||||
IF(HAVE_LIBDSOUND OR WIN32)
|
||||
SET(HAVE_DSOUND 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/dsound.c)
|
||||
|
||||
SET(CMAKE_REQUIRED_LIBRARIES dsound)
|
||||
CHECK_C_SOURCE_COMPILES("int main() {return 0;}" HAVE_LIBDSOUND)
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "")
|
||||
# CHECK_LIBRARY_EXISTS(dsound DirectSoundCreate "" HAVE_LIBDSOUND)
|
||||
IF(HAVE_LIBDSOUND)
|
||||
SET(EXTRA_LIBS dsound ${EXTRA_LIBS})
|
||||
IF(WIN32)
|
||||
SET(BACKENDS "${BACKENDS} DirectSound,")
|
||||
ELSE()
|
||||
SET(BACKENDS "${BACKENDS} DirectSound \(linked\),")
|
||||
SET(EXTRA_LIBS dsound ${EXTRA_LIBS})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
@@ -315,6 +349,42 @@ IF(HAVE_WINDOWS_H)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Check PortAudio backend
|
||||
IF(PORTAUDIO)
|
||||
CHECK_INCLUDE_FILE(portaudio.h HAVE_PORTAUDIO_H)
|
||||
IF(HAVE_PORTAUDIO_H)
|
||||
CHECK_LIBRARY_EXISTS(portaudio Pa_Initialize "" HAVE_LIBPORTAUDIO)
|
||||
IF(HAVE_LIBPORTAUDIO)
|
||||
SET(HAVE_PORTAUDIO 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/portaudio.c)
|
||||
IF(HAVE_DLFCN_H)
|
||||
SET(BACKENDS "${BACKENDS} PortAudio,")
|
||||
ELSE()
|
||||
SET(BACKENDS "${BACKENDS} PortAudio \(linked\),")
|
||||
SET(EXTRA_LIBS portaudio ${EXTRA_LIBS})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# Check PortAudio backend
|
||||
IF(PULSEAUDIO)
|
||||
CHECK_INCLUDE_FILE(pulse/pulseaudio.h HAVE_PULSE_PULSEAUDIO_H)
|
||||
IF(HAVE_PULSE_PULSEAUDIO_H)
|
||||
CHECK_LIBRARY_EXISTS(pulse pa_context_new "" HAVE_LIBPULSE)
|
||||
IF(HAVE_LIBPULSE)
|
||||
SET(HAVE_PULSEAUDIO 1)
|
||||
SET(ALC_OBJS ${ALC_OBJS} Alc/pulseaudio.c)
|
||||
IF(HAVE_DLFCN_H)
|
||||
SET(BACKENDS "${BACKENDS} PulseAudio,")
|
||||
ELSE()
|
||||
SET(BACKENDS "${BACKENDS} PulseAudio \(linked\),")
|
||||
SET(EXTRA_LIBS pulse ${EXTRA_LIBS})
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# This is always available
|
||||
SET(BACKENDS "${BACKENDS} WaveFile")
|
||||
|
||||
@@ -347,15 +417,6 @@ SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION}
|
||||
IF(WIN32)
|
||||
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
|
||||
ENDIF()
|
||||
IF(XCOMPILEWIN32)
|
||||
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "" SUFFIX .dll)
|
||||
IF(EXAMPLES)
|
||||
SET(EXAMPLES OFF)
|
||||
MESSAGE(STATUS "")
|
||||
MESSAGE(STATUS "Building examples disabled when cross-compiling")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES OUTPUT_NAME ${LIBNAME})
|
||||
|
||||
TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS})
|
||||
|
||||
@@ -371,7 +432,15 @@ INSTALL(FILES include/AL/al.h
|
||||
DESTINATION include/AL
|
||||
)
|
||||
INSTALL(FILES "${OpenAL_BINARY_DIR}/admin/pkgconfig/openal.pc"
|
||||
DESTINATION lib/pkgconfig)
|
||||
DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
|
||||
|
||||
# Install alsoft.conf configuration file
|
||||
IF(ALSOFT_CONFIG)
|
||||
INSTALL(FILES alsoftrc.sample
|
||||
DESTINATION /etc/openal
|
||||
RENAME alsoft.conf
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(EXAMPLES)
|
||||
ADD_EXECUTABLE(openal-info examples/openal-info.c)
|
||||
@@ -388,7 +457,7 @@ MESSAGE(STATUS "Building OpenAL with support for the following backends:")
|
||||
MESSAGE(STATUS " ${BACKENDS}")
|
||||
MESSAGE(STATUS "")
|
||||
|
||||
IF(WIN32 OR XCOMPILEWIN32)
|
||||
IF(WIN32)
|
||||
IF(NOT HAVE_DSOUND)
|
||||
MESSAGE(STATUS "WARNING: Building the Windows version without DirectSound output")
|
||||
MESSAGE(STATUS " This is probably NOT what you want!")
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "AL/al.h"
|
||||
#include "alEffect.h"
|
||||
#include "alFilter.h"
|
||||
#include "alReverb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -16,6 +15,8 @@ extern "C" {
|
||||
|
||||
#define AL_EFFECTSLOT_NULL 0x0000
|
||||
|
||||
typedef struct ALeffectState ALeffectState;
|
||||
|
||||
typedef struct ALeffectslot
|
||||
{
|
||||
ALeffect effect;
|
||||
@@ -23,7 +24,9 @@ typedef struct ALeffectslot
|
||||
ALfloat Gain;
|
||||
ALboolean AuxSendAuto;
|
||||
|
||||
ALverbState *ReverbState;
|
||||
ALeffectState *EffectState;
|
||||
|
||||
ALfloat WetBuffer[BUFFERSIZE];
|
||||
|
||||
ALuint refcount;
|
||||
|
||||
@@ -49,6 +52,22 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, A
|
||||
|
||||
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
|
||||
|
||||
|
||||
struct ALeffectState {
|
||||
ALvoid (*Destroy)(ALeffectState *State);
|
||||
ALvoid (*Update)(ALeffectState *State, ALCcontext *Context, ALeffect *Effect);
|
||||
ALvoid (*Process)(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]);
|
||||
};
|
||||
|
||||
ALeffectState *EAXVerbCreate(ALCcontext *Context);
|
||||
ALeffectState *VerbCreate(ALCcontext *Context);
|
||||
ALeffectState *EchoCreate(ALCcontext *Context);
|
||||
|
||||
#define ALEffect_Destroy(a) ((a)->Destroy((a)))
|
||||
#define ALEffect_Update(a,b,c) ((a)->Update((a),(b),(c)))
|
||||
#define ALEffect_Process(a,b,c,d,e) ((a)->Process((a),(b),(c),(d),(e)))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+181
-3
@@ -1,3 +1,5 @@
|
||||
// NOTE: The effect structure is getting too large, it may be a good idea to
|
||||
// start using a union or another form of unified storage.
|
||||
#ifndef _AL_EFFECT_H_
|
||||
#define _AL_EFFECT_H_
|
||||
|
||||
@@ -22,6 +24,7 @@ extern "C" {
|
||||
#define AL_EFFECT_AUTOWAH 0x000A
|
||||
#define AL_EFFECT_COMPRESSOR 0x000B
|
||||
#define AL_EFFECT_EQUALIZER 0x000C
|
||||
#define AL_EFFECT_EAXREVERB 0x8000
|
||||
|
||||
#define AL_REVERB_DENSITY 0x0001
|
||||
#define AL_REVERB_DIFFUSION 0x0002
|
||||
@@ -37,23 +40,176 @@ extern "C" {
|
||||
#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C
|
||||
#define AL_REVERB_DECAY_HFLIMIT 0x000D
|
||||
|
||||
#define AL_REVERB_MIN_DENSITY (0.0f)
|
||||
#define AL_REVERB_MAX_DENSITY (1.0f)
|
||||
#define AL_REVERB_DEFAULT_DENSITY (1.0f)
|
||||
#define AL_REVERB_MIN_DIFFUSION (0.0f)
|
||||
#define AL_REVERB_MAX_DIFFUSION (1.0f)
|
||||
#define AL_REVERB_DEFAULT_DIFFUSION (1.0f)
|
||||
#define AL_REVERB_MIN_GAIN (0.0f)
|
||||
#define AL_REVERB_MAX_GAIN (1.0f)
|
||||
#define AL_REVERB_DEFAULT_GAIN (0.32f)
|
||||
#define AL_REVERB_MIN_GAINHF (0.0f)
|
||||
#define AL_REVERB_MAX_GAINHF (1.0f)
|
||||
#define AL_REVERB_DEFAULT_GAINHF (0.89f)
|
||||
#define AL_REVERB_MIN_DECAY_TIME (0.1f)
|
||||
#define AL_REVERB_MAX_DECAY_TIME (20.0f)
|
||||
#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f)
|
||||
#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f)
|
||||
#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f)
|
||||
#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f)
|
||||
#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f)
|
||||
#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f)
|
||||
#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
|
||||
#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f)
|
||||
#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f)
|
||||
#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
|
||||
#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f)
|
||||
#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f)
|
||||
#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
|
||||
#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f)
|
||||
#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f)
|
||||
#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
|
||||
#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
|
||||
#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
|
||||
#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
|
||||
#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
|
||||
#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
#define AL_REVERB_MIN_DECAY_HFLIMIT (AL_FALSE)
|
||||
#define AL_REVERB_MAX_DECAY_HFLIMIT (AL_TRUE)
|
||||
#define AL_REVERB_DEFAULT_DECAY_HFLIMIT (AL_TRUE)
|
||||
|
||||
#define AL_ECHO_DELAY 0x0001
|
||||
#define AL_ECHO_LRDELAY 0x0002
|
||||
#define AL_ECHO_DAMPING 0x0003
|
||||
#define AL_ECHO_FEEDBACK 0x0004
|
||||
#define AL_ECHO_SPREAD 0x0005
|
||||
|
||||
#define AL_ECHO_MIN_DELAY (0.0f)
|
||||
#define AL_ECHO_MAX_DELAY (0.207f)
|
||||
#define AL_ECHO_DEFAULT_DELAY (0.1f)
|
||||
#define AL_ECHO_MIN_LRDELAY (0.0f)
|
||||
#define AL_ECHO_MAX_LRDELAY (0.404f)
|
||||
#define AL_ECHO_DEFAULT_LRDELAY (0.1f)
|
||||
#define AL_ECHO_MIN_DAMPING (0.0f)
|
||||
#define AL_ECHO_MAX_DAMPING (0.99f)
|
||||
#define AL_ECHO_DEFAULT_DAMPING (0.5f)
|
||||
#define AL_ECHO_MIN_FEEDBACK (0.0f)
|
||||
#define AL_ECHO_MAX_FEEDBACK (1.0f)
|
||||
#define AL_ECHO_DEFAULT_FEEDBACK (0.5f)
|
||||
#define AL_ECHO_MIN_SPREAD (-1.0f)
|
||||
#define AL_ECHO_MAX_SPREAD (1.0f)
|
||||
#define AL_ECHO_DEFAULT_SPREAD (-1.0f)
|
||||
|
||||
#define AL_EAXREVERB_DENSITY 0x0001
|
||||
#define AL_EAXREVERB_DIFFUSION 0x0002
|
||||
#define AL_EAXREVERB_GAIN 0x0003
|
||||
#define AL_EAXREVERB_GAINHF 0x0004
|
||||
#define AL_EAXREVERB_GAINLF 0x0005
|
||||
#define AL_EAXREVERB_DECAY_TIME 0x0006
|
||||
#define AL_EAXREVERB_DECAY_HFRATIO 0x0007
|
||||
#define AL_EAXREVERB_DECAY_LFRATIO 0x0008
|
||||
#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009
|
||||
#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A
|
||||
#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B
|
||||
#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C
|
||||
#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D
|
||||
#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E
|
||||
#define AL_EAXREVERB_ECHO_TIME 0x000F
|
||||
#define AL_EAXREVERB_ECHO_DEPTH 0x0010
|
||||
#define AL_EAXREVERB_MODULATION_TIME 0x0011
|
||||
#define AL_EAXREVERB_MODULATION_DEPTH 0x0012
|
||||
#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013
|
||||
#define AL_EAXREVERB_HFREFERENCE 0x0014
|
||||
#define AL_EAXREVERB_LFREFERENCE 0x0015
|
||||
#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016
|
||||
#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017
|
||||
|
||||
#define AL_EAXREVERB_MIN_DENSITY (0.0f)
|
||||
#define AL_EAXREVERB_MAX_DENSITY (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f)
|
||||
#define AL_EAXREVERB_MIN_DIFFUSION (0.0f)
|
||||
#define AL_EAXREVERB_MAX_DIFFUSION (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f)
|
||||
#define AL_EAXREVERB_MIN_GAIN (0.0f)
|
||||
#define AL_EAXREVERB_MAX_GAIN (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_GAIN (0.32f)
|
||||
#define AL_EAXREVERB_MIN_GAINHF (0.0f)
|
||||
#define AL_EAXREVERB_MAX_GAINHF (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f)
|
||||
#define AL_EAXREVERB_MIN_GAINLF (0.0f)
|
||||
#define AL_EAXREVERB_MAX_GAINLF (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f)
|
||||
#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f)
|
||||
#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f)
|
||||
#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f)
|
||||
#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f)
|
||||
#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f)
|
||||
#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f)
|
||||
#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f)
|
||||
#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f)
|
||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f)
|
||||
#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f)
|
||||
#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f)
|
||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f)
|
||||
#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f)
|
||||
#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f)
|
||||
#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f)
|
||||
#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f)
|
||||
#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f)
|
||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f)
|
||||
#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f)
|
||||
#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f)
|
||||
#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f)
|
||||
#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f)
|
||||
#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f)
|
||||
#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f)
|
||||
#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f)
|
||||
#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f)
|
||||
#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f)
|
||||
#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f)
|
||||
#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f)
|
||||
#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f)
|
||||
#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f)
|
||||
#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f)
|
||||
#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f)
|
||||
#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f)
|
||||
#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f)
|
||||
#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f)
|
||||
#define AL_EAXREVERB_MIN_DECAY_HFLIMIT (AL_FALSE)
|
||||
#define AL_EAXREVERB_MAX_DECAY_HFLIMIT (AL_TRUE)
|
||||
#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT (AL_TRUE)
|
||||
|
||||
enum {
|
||||
REVERB = 0,
|
||||
EAXREVERB = 0,
|
||||
REVERB,
|
||||
ECHO,
|
||||
|
||||
MAX_EFFECTS
|
||||
};
|
||||
extern ALboolean DisabledEffects[MAX_EFFECTS];
|
||||
|
||||
|
||||
typedef struct ALeffect_struct
|
||||
{
|
||||
// Effect type (AL_EFFECT_NULL, ...)
|
||||
ALenum type;
|
||||
|
||||
struct {
|
||||
// Shared Reverb Properties
|
||||
ALfloat Density;
|
||||
ALfloat Diffusion;
|
||||
|
||||
ALfloat Gain;
|
||||
ALfloat GainHF;
|
||||
ALfloat DecayTime;
|
||||
@@ -65,8 +221,30 @@ typedef struct ALeffect_struct
|
||||
ALfloat AirAbsorptionGainHF;
|
||||
ALfloat RoomRolloffFactor;
|
||||
ALboolean DecayHFLimit;
|
||||
|
||||
// Additional EAX Reverb Properties
|
||||
ALfloat GainLF;
|
||||
ALfloat DecayLFRatio;
|
||||
ALfloat ReflectionsPan[3];
|
||||
ALfloat LateReverbPan[3];
|
||||
ALfloat EchoTime;
|
||||
ALfloat EchoDepth;
|
||||
ALfloat ModulationTime;
|
||||
ALfloat ModulationDepth;
|
||||
ALfloat HFReference;
|
||||
ALfloat LFReference;
|
||||
} Reverb;
|
||||
|
||||
struct {
|
||||
ALfloat Delay;
|
||||
ALfloat LRDelay;
|
||||
|
||||
ALfloat Damping;
|
||||
ALfloat Feedback;
|
||||
|
||||
ALfloat Spread;
|
||||
} Echo;
|
||||
|
||||
// Index to itself
|
||||
ALuint effect;
|
||||
|
||||
|
||||
@@ -2,16 +2,54 @@
|
||||
#define _AL_FILTER_H_
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "alu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
ALfloat history[4];
|
||||
ALfloat coeff;
|
||||
#ifndef _MSC_VER
|
||||
ALfloat history[0];
|
||||
#else
|
||||
ALfloat history[1];
|
||||
#endif
|
||||
} FILTER;
|
||||
|
||||
static __inline ALfloat lpFilter4P(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;
|
||||
output = output + (history[1]-output)*a;
|
||||
history[1] = output;
|
||||
output = output + (history[2]-output)*a;
|
||||
history[2] = output;
|
||||
output = output + (history[3]-output)*a;
|
||||
history[3] = output;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
static __inline ALfloat lpFilter2P(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;
|
||||
output = output + (history[1]-output)*a;
|
||||
history[1] = output;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
#define AL_FILTER_TYPE 0x8001
|
||||
|
||||
#define AL_FILTER_NULL 0x0000
|
||||
|
||||
+43
-17
@@ -3,13 +3,16 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alu.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef HAVE_FENV_H
|
||||
#include <fenv.h>
|
||||
#endif
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
@@ -98,28 +101,37 @@ static inline void Sleep(ALuint t)
|
||||
#define max(x,y) (((x)>(y))?(x):(y))
|
||||
#endif
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.h"
|
||||
#include "alListener.h"
|
||||
#include "alu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern char _alDebug[256];
|
||||
static __inline void al_print(const char *fname, unsigned int line, const char *fmt, ...)
|
||||
{
|
||||
const char *fn;
|
||||
char str[256];
|
||||
int i;
|
||||
|
||||
#define AL_PRINT(...) do { \
|
||||
int _al_print_i; \
|
||||
const char *_al_print_fn = strrchr(__FILE__, '/'); \
|
||||
if(!_al_print_fn) _al_print_fn = __FILE__; \
|
||||
else _al_print_fn += 1; \
|
||||
_al_print_i = snprintf(_alDebug, sizeof(_alDebug), "AL lib: %s:%d: ", _al_print_fn, __LINE__); \
|
||||
if(_al_print_i < (int)sizeof(_alDebug) && _al_print_i > 0) \
|
||||
snprintf(_alDebug+_al_print_i, sizeof(_alDebug)-_al_print_i, __VA_ARGS__); \
|
||||
_alDebug[sizeof(_alDebug)-1] = 0; \
|
||||
fprintf(stderr, "%s", _alDebug); \
|
||||
} while(0)
|
||||
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
|
||||
@@ -129,6 +141,9 @@ extern char _alDebug[256];
|
||||
|
||||
#define LOWPASSFREQCUTOFF (5000)
|
||||
|
||||
#define QUADRANT_NUM 128
|
||||
#define LUT_NUM (4 * QUADRANT_NUM)
|
||||
|
||||
|
||||
typedef struct {
|
||||
ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*);
|
||||
@@ -147,7 +162,9 @@ void alc_oss_init(BackendFuncs *func_list);
|
||||
void alc_solaris_init(BackendFuncs *func_list);
|
||||
void alcDSoundInit(BackendFuncs *func_list);
|
||||
void alcWinMMInit(BackendFuncs *FuncList);
|
||||
void alc_pa_init(BackendFuncs *func_list);
|
||||
void alc_wave_init(BackendFuncs *func_list);
|
||||
void alc_pulse_init(BackendFuncs *func_list);
|
||||
|
||||
|
||||
struct ALCdevice_struct
|
||||
@@ -162,6 +179,8 @@ struct ALCdevice_struct
|
||||
|
||||
// Maximum number of sources that can be created
|
||||
ALuint MaxNoOfSources;
|
||||
// Maximum number of slots that can be created
|
||||
ALuint AuxiliaryEffectSlotMax;
|
||||
|
||||
// Context created on this device
|
||||
ALCcontext *Context;
|
||||
@@ -205,6 +224,13 @@ struct ALCcontext_struct
|
||||
ALint lNumMonoSources;
|
||||
ALint lNumStereoSources;
|
||||
|
||||
ALuint NumSends;
|
||||
|
||||
ALfloat PanningLUT[OUTPUTCHANNELS * LUT_NUM];
|
||||
ALint NumChan;
|
||||
|
||||
ALfloat ChannelMatrix[OUTPUTCHANNELS][OUTPUTCHANNELS];
|
||||
|
||||
ALCdevice *Device;
|
||||
const ALCchar *ExtensionList;
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef _AL_REVERB_H_
|
||||
#define _AL_REVERB_H_
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alMain.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alEffect.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ALverbState ALverbState;
|
||||
|
||||
ALverbState *VerbCreate(ALCcontext *Context);
|
||||
ALvoid VerbDestroy(ALverbState *State);
|
||||
ALvoid VerbUpdate(ALCcontext *Context, struct ALeffectslot *Slot, ALeffect *Effect);
|
||||
ALvoid VerbProcess(ALverbState *State, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
|
||||
#define AL_NUM_SOURCE_PARAMS 128
|
||||
|
||||
/* This cannot be changed without working on the code! */
|
||||
#define MAX_SENDS 1
|
||||
#define MAX_SENDS 2
|
||||
|
||||
#include "alFilter.h"
|
||||
#include "alu.h"
|
||||
@@ -48,6 +47,7 @@ typedef struct ALsource
|
||||
ALfloat vOrientation[3];
|
||||
ALboolean bHeadRelative;
|
||||
ALboolean bLooping;
|
||||
ALenum DistanceModel;
|
||||
|
||||
ALuint ulBufferID;
|
||||
|
||||
@@ -69,6 +69,7 @@ typedef struct ALsource
|
||||
struct ALeffectslot *Slot;
|
||||
ALfilter WetFilter;
|
||||
FILTER iirFilter;
|
||||
ALfloat history[2];
|
||||
} Send[MAX_SENDS];
|
||||
|
||||
ALboolean DryGainHFAuto;
|
||||
@@ -77,6 +78,7 @@ typedef struct ALsource
|
||||
ALfloat OuterGainHF;
|
||||
|
||||
FILTER iirFilter;
|
||||
ALfloat history[OUTPUTCHANNELS*2];
|
||||
|
||||
ALfloat AirAbsorptionFactor;
|
||||
|
||||
@@ -95,7 +97,7 @@ typedef struct ALsource
|
||||
|
||||
// Current gains, which are ramped while mixed
|
||||
ALfloat DryGains[OUTPUTCHANNELS];
|
||||
ALfloat WetGain;
|
||||
ALfloat WetGains[MAX_SENDS];
|
||||
ALboolean FirstStart;
|
||||
|
||||
struct ALsource *next;
|
||||
|
||||
+124
-3
@@ -3,6 +3,48 @@
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#include "AL/alext.h"
|
||||
|
||||
#ifdef HAVE_FLOAT_H
|
||||
#include <float.h>
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SQRTF
|
||||
#define aluSqrt(x) ((ALfloat)sqrtf((float)(x)))
|
||||
#else
|
||||
#define aluSqrt(x) ((ALfloat)sqrt((double)(x)))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ACOSF
|
||||
#define aluAcos(x) ((ALfloat)acosf((float)(x)))
|
||||
#else
|
||||
#define aluAcos(x) ((ALfloat)acos((double)(x)))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ATANF
|
||||
#define aluAtan(x) ((ALfloat)atanf((float)(x)))
|
||||
#else
|
||||
#define aluAtan(x) ((ALfloat)atan((double)(x)))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FABSF
|
||||
#define aluFabs(x) ((ALfloat)fabsf((float)(x)))
|
||||
#else
|
||||
#define aluFabs(x) ((ALfloat)fabs((double)(x)))
|
||||
#endif
|
||||
|
||||
// fixes for mingw32.
|
||||
#if defined(max) && !defined(__max)
|
||||
#define __max max
|
||||
#endif
|
||||
#if defined(min) && !defined(__min)
|
||||
#define __min min
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -11,20 +53,99 @@ extern "C" {
|
||||
enum {
|
||||
FRONT_LEFT = 0,
|
||||
FRONT_RIGHT,
|
||||
FRONT_CENTER,
|
||||
SIDE_LEFT,
|
||||
SIDE_RIGHT,
|
||||
BACK_LEFT,
|
||||
BACK_RIGHT,
|
||||
CENTER,
|
||||
BACK_CENTER,
|
||||
LFE,
|
||||
|
||||
OUTPUTCHANNELS
|
||||
};
|
||||
|
||||
#define BUFFERSIZE 24000
|
||||
|
||||
extern ALboolean DuplicateStereo;
|
||||
|
||||
__inline ALuint aluBytesFromFormat(ALenum format);
|
||||
__inline ALuint aluChannelsFromFormat(ALenum format);
|
||||
/* NOTE: The AL_FORMAT_REAR* enums aren't handled here be cause they're
|
||||
* converted to AL_FORMAT_QUAD* when loaded */
|
||||
static __inline ALuint aluBytesFromFormat(ALenum format)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case AL_FORMAT_MONO8:
|
||||
case AL_FORMAT_STEREO8:
|
||||
case AL_FORMAT_QUAD8_LOKI:
|
||||
case AL_FORMAT_QUAD8:
|
||||
case AL_FORMAT_51CHN8:
|
||||
case AL_FORMAT_61CHN8:
|
||||
case AL_FORMAT_71CHN8:
|
||||
return 1;
|
||||
|
||||
case AL_FORMAT_MONO16:
|
||||
case AL_FORMAT_STEREO16:
|
||||
case AL_FORMAT_QUAD16_LOKI:
|
||||
case AL_FORMAT_QUAD16:
|
||||
case AL_FORMAT_51CHN16:
|
||||
case AL_FORMAT_61CHN16:
|
||||
case AL_FORMAT_71CHN16:
|
||||
return 2;
|
||||
|
||||
case AL_FORMAT_MONO_FLOAT32:
|
||||
case AL_FORMAT_STEREO_FLOAT32:
|
||||
case AL_FORMAT_QUAD32:
|
||||
case AL_FORMAT_51CHN32:
|
||||
case AL_FORMAT_61CHN32:
|
||||
case AL_FORMAT_71CHN32:
|
||||
return 4;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
static __inline ALuint aluChannelsFromFormat(ALenum format)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case AL_FORMAT_MONO8:
|
||||
case AL_FORMAT_MONO16:
|
||||
case AL_FORMAT_MONO_FLOAT32:
|
||||
return 1;
|
||||
|
||||
case AL_FORMAT_STEREO8:
|
||||
case AL_FORMAT_STEREO16:
|
||||
case AL_FORMAT_STEREO_FLOAT32:
|
||||
return 2;
|
||||
|
||||
case AL_FORMAT_QUAD8_LOKI:
|
||||
case AL_FORMAT_QUAD16_LOKI:
|
||||
case AL_FORMAT_QUAD8:
|
||||
case AL_FORMAT_QUAD16:
|
||||
case AL_FORMAT_QUAD32:
|
||||
return 4;
|
||||
|
||||
case AL_FORMAT_51CHN8:
|
||||
case AL_FORMAT_51CHN16:
|
||||
case AL_FORMAT_51CHN32:
|
||||
return 6;
|
||||
|
||||
case AL_FORMAT_61CHN8:
|
||||
case AL_FORMAT_61CHN16:
|
||||
case AL_FORMAT_61CHN32:
|
||||
return 7;
|
||||
|
||||
case AL_FORMAT_71CHN8:
|
||||
case AL_FORMAT_71CHN16:
|
||||
case AL_FORMAT_71CHN32:
|
||||
return 8;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ALvoid aluInitPanning(ALCcontext *Context);
|
||||
ALvoid aluMixData(ALCcontext *context,ALvoid *buffer,ALsizei size,ALenum format);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
+30
-14
@@ -29,7 +29,6 @@
|
||||
#include "alAuxEffectSlot.h"
|
||||
#include "alThunk.h"
|
||||
#include "alError.h"
|
||||
#include "alReverb.h"
|
||||
|
||||
|
||||
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
|
||||
@@ -38,7 +37,7 @@ static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot,
|
||||
ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALsizei i;
|
||||
ALsizei i, j;
|
||||
|
||||
Context = alcGetCurrentContext();
|
||||
if(!Context)
|
||||
@@ -50,8 +49,9 @@ ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
/* NOTE: We only support one slot currently */
|
||||
if(n == 1 && Context->AuxiliaryEffectSlotCount == 0)
|
||||
ALCdevice *Device = alcGetContextsDevice(Context);
|
||||
|
||||
if(Context->AuxiliaryEffectSlotCount+n <= Device->AuxiliaryEffectSlotMax)
|
||||
{
|
||||
// Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
|
||||
if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
|
||||
@@ -74,6 +74,8 @@ ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||
|
||||
(*list)->Gain = 1.0;
|
||||
(*list)->AuxSendAuto = AL_TRUE;
|
||||
for(j = 0;j < BUFFERSIZE;j++)
|
||||
(*list)->WetBuffer[j] = 0.0f;
|
||||
(*list)->refcount = 0;
|
||||
|
||||
effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
|
||||
@@ -149,7 +151,8 @@ ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||
*list = (*list)->next;
|
||||
ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
|
||||
|
||||
VerbDestroy(ALAuxiliaryEffectSlot->ReverbState);
|
||||
if(ALAuxiliaryEffectSlot->EffectState)
|
||||
ALEffect_Destroy(ALAuxiliaryEffectSlot->EffectState);
|
||||
|
||||
memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
|
||||
free(ALAuxiliaryEffectSlot);
|
||||
@@ -468,20 +471,32 @@ ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, A
|
||||
|
||||
static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
|
||||
{
|
||||
if((!effect) || (effect->type != ALEffectSlot->effect.type))
|
||||
{
|
||||
ALeffectState *NewState = NULL;
|
||||
if(effect)
|
||||
{
|
||||
if(effect->type == AL_EFFECT_EAXREVERB)
|
||||
NewState = EAXVerbCreate(Context);
|
||||
else if(effect->type == AL_EFFECT_REVERB)
|
||||
NewState = VerbCreate(Context);
|
||||
else if(effect->type == AL_EFFECT_ECHO)
|
||||
NewState = EchoCreate(Context);
|
||||
/* No new state? An error occured.. */
|
||||
if(!NewState)
|
||||
return;
|
||||
}
|
||||
if(ALEffectSlot->EffectState)
|
||||
ALEffect_Destroy(ALEffectSlot->EffectState);
|
||||
ALEffectSlot->EffectState = NewState;
|
||||
}
|
||||
if(!effect)
|
||||
{
|
||||
memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
|
||||
VerbDestroy(ALEffectSlot->ReverbState);
|
||||
ALEffectSlot->ReverbState = NULL;
|
||||
return;
|
||||
}
|
||||
if(effect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
if(!ALEffectSlot->ReverbState)
|
||||
ALEffectSlot->ReverbState = VerbCreate(Context);
|
||||
VerbUpdate(Context, ALEffectSlot, effect);
|
||||
}
|
||||
memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
|
||||
ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
|
||||
}
|
||||
|
||||
|
||||
@@ -498,7 +513,8 @@ ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
|
||||
Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
|
||||
|
||||
// Release effectslot structure
|
||||
VerbDestroy(temp->ReverbState);
|
||||
if(temp->EffectState)
|
||||
ALEffect_Destroy(temp->EffectState);
|
||||
ALTHUNK_REMOVEENTRY(temp->effectslot);
|
||||
|
||||
memset(temp, 0, sizeof(ALeffectslot));
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
||||
*/
|
||||
|
||||
#define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
+627
-33
@@ -21,6 +21,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
@@ -170,19 +171,22 @@ ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
|
||||
if(param == AL_EFFECT_TYPE)
|
||||
{
|
||||
ALboolean isOk = (iValue == AL_EFFECT_NULL ||
|
||||
(iValue == AL_EFFECT_REVERB && !DisabledEffects[REVERB]));
|
||||
(iValue == AL_EFFECT_EAXREVERB && !DisabledEffects[EAXREVERB]) ||
|
||||
(iValue == AL_EFFECT_REVERB && !DisabledEffects[REVERB]) ||
|
||||
(iValue == AL_EFFECT_ECHO && !DisabledEffects[ECHO]));
|
||||
|
||||
if(isOk)
|
||||
InitEffectParams(ALEffect, iValue);
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
else if(ALEffect->type == AL_EFFECT_EAXREVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_REVERB_DECAY_HFLIMIT:
|
||||
if(iValue == AL_TRUE || iValue == AL_FALSE)
|
||||
case AL_EAXREVERB_DECAY_HFLIMIT:
|
||||
if(iValue >= AL_EAXREVERB_MIN_DECAY_HFLIMIT &&
|
||||
iValue <= AL_EAXREVERB_MAX_DECAY_HFLIMIT)
|
||||
ALEffect->Reverb.DecayHFLimit = iValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
@@ -193,6 +197,32 @@ ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_REVERB_DECAY_HFLIMIT:
|
||||
if(iValue >= AL_REVERB_MIN_DECAY_HFLIMIT &&
|
||||
iValue <= AL_REVERB_MAX_DECAY_HFLIMIT)
|
||||
ALEffect->Reverb.DecayHFLimit = iValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_ECHO)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
}
|
||||
@@ -217,6 +247,19 @@ ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
|
||||
{
|
||||
alEffecti(effect, param, piValues[0]);
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_EAXREVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EAXREVERB_DECAY_HFLIMIT:
|
||||
alEffecti(effect, param, piValues[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
switch(param)
|
||||
@@ -230,6 +273,15 @@ ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_ECHO)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
}
|
||||
@@ -250,89 +302,269 @@ ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
|
||||
{
|
||||
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
|
||||
|
||||
if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
if(ALEffect->type == AL_EFFECT_EAXREVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EAXREVERB_DENSITY:
|
||||
if(flValue >= AL_EAXREVERB_MIN_DENSITY &&
|
||||
flValue <= AL_EAXREVERB_MAX_DENSITY)
|
||||
ALEffect->Reverb.Density = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_DIFFUSION:
|
||||
if(flValue >= AL_EAXREVERB_MIN_DIFFUSION &&
|
||||
flValue <= AL_EAXREVERB_MAX_DIFFUSION)
|
||||
ALEffect->Reverb.Diffusion = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_GAIN:
|
||||
if(flValue >= AL_EAXREVERB_MIN_GAIN &&
|
||||
flValue <= AL_EAXREVERB_MAX_GAIN)
|
||||
ALEffect->Reverb.Gain = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_GAINHF:
|
||||
if(flValue >= AL_EAXREVERB_MIN_GAINHF &&
|
||||
flValue <= AL_EAXREVERB_MAX_GAIN)
|
||||
ALEffect->Reverb.GainHF = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_GAINLF:
|
||||
if(flValue >= AL_EAXREVERB_MIN_GAINLF &&
|
||||
flValue <= AL_EAXREVERB_MAX_GAINLF)
|
||||
ALEffect->Reverb.GainLF = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_DECAY_TIME:
|
||||
if(flValue >= AL_EAXREVERB_MIN_DECAY_TIME &&
|
||||
flValue <= AL_EAXREVERB_MAX_DECAY_TIME)
|
||||
ALEffect->Reverb.DecayTime = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_DECAY_HFRATIO:
|
||||
if(flValue >= AL_EAXREVERB_MIN_DECAY_HFRATIO &&
|
||||
flValue <= AL_EAXREVERB_MAX_DECAY_HFRATIO)
|
||||
ALEffect->Reverb.DecayHFRatio = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_DECAY_LFRATIO:
|
||||
if(flValue >= AL_EAXREVERB_MIN_DECAY_LFRATIO &&
|
||||
flValue <= AL_EAXREVERB_MAX_DECAY_LFRATIO)
|
||||
ALEffect->Reverb.DecayLFRatio = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_REFLECTIONS_GAIN:
|
||||
if(flValue >= AL_EAXREVERB_MIN_REFLECTIONS_GAIN &&
|
||||
flValue <= AL_EAXREVERB_MAX_REFLECTIONS_GAIN)
|
||||
ALEffect->Reverb.ReflectionsGain = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_REFLECTIONS_DELAY:
|
||||
if(flValue >= AL_EAXREVERB_MIN_REFLECTIONS_DELAY &&
|
||||
flValue <= AL_EAXREVERB_MAX_REFLECTIONS_DELAY)
|
||||
ALEffect->Reverb.ReflectionsDelay = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_LATE_REVERB_GAIN:
|
||||
if(flValue >= AL_EAXREVERB_MIN_LATE_REVERB_GAIN &&
|
||||
flValue <= AL_EAXREVERB_MAX_LATE_REVERB_GAIN)
|
||||
ALEffect->Reverb.LateReverbGain = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_LATE_REVERB_DELAY:
|
||||
if(flValue >= AL_EAXREVERB_MIN_LATE_REVERB_DELAY &&
|
||||
flValue <= AL_EAXREVERB_MAX_LATE_REVERB_DELAY)
|
||||
ALEffect->Reverb.LateReverbDelay = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
|
||||
if(flValue >= AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF &&
|
||||
flValue <= AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF)
|
||||
ALEffect->Reverb.AirAbsorptionGainHF = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_ECHO_TIME:
|
||||
if(flValue >= AL_EAXREVERB_MIN_ECHO_TIME &&
|
||||
flValue <= AL_EAXREVERB_MAX_ECHO_TIME)
|
||||
ALEffect->Reverb.EchoTime = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_ECHO_DEPTH:
|
||||
if(flValue >= AL_EAXREVERB_MIN_ECHO_DEPTH &&
|
||||
flValue <= AL_EAXREVERB_MAX_ECHO_DEPTH)
|
||||
ALEffect->Reverb.EchoDepth = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_MODULATION_TIME:
|
||||
if(flValue >= AL_EAXREVERB_MIN_MODULATION_TIME &&
|
||||
flValue <= AL_EAXREVERB_MAX_MODULATION_TIME)
|
||||
ALEffect->Reverb.ModulationTime = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_MODULATION_DEPTH:
|
||||
if(flValue >= AL_EAXREVERB_MIN_MODULATION_DEPTH &&
|
||||
flValue <= AL_EAXREVERB_MAX_MODULATION_DEPTH)
|
||||
ALEffect->Reverb.ModulationDepth = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_HFREFERENCE:
|
||||
if(flValue >= AL_EAXREVERB_MIN_HFREFERENCE &&
|
||||
flValue <= AL_EAXREVERB_MAX_HFREFERENCE)
|
||||
ALEffect->Reverb.HFReference = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_LFREFERENCE:
|
||||
if(flValue >= AL_EAXREVERB_MIN_LFREFERENCE &&
|
||||
flValue <= AL_EAXREVERB_MAX_LFREFERENCE)
|
||||
ALEffect->Reverb.LFReference = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
|
||||
if(flValue >= 0.0f && flValue <= 10.0f)
|
||||
ALEffect->Reverb.RoomRolloffFactor = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_REVERB_DENSITY:
|
||||
if(flValue >= 0.0f && flValue <= 1.0f)
|
||||
if(flValue >= AL_REVERB_MIN_DENSITY &&
|
||||
flValue <= AL_REVERB_MAX_DENSITY)
|
||||
ALEffect->Reverb.Density = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_DIFFUSION:
|
||||
if(flValue >= 0.0f && flValue <= 1.0f)
|
||||
if(flValue >= AL_REVERB_MIN_DIFFUSION &&
|
||||
flValue <= AL_REVERB_MAX_DIFFUSION)
|
||||
ALEffect->Reverb.Diffusion = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_GAIN:
|
||||
if(flValue >= 0.0f && flValue <= 1.0f)
|
||||
if(flValue >= AL_REVERB_MIN_GAIN &&
|
||||
flValue <= AL_REVERB_MAX_GAIN)
|
||||
ALEffect->Reverb.Gain = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_GAINHF:
|
||||
if(flValue >= 0.0f && flValue <= 1.0f)
|
||||
if(flValue >= AL_REVERB_MIN_GAINHF &&
|
||||
flValue <= AL_REVERB_MAX_GAINHF)
|
||||
ALEffect->Reverb.GainHF = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_DECAY_TIME:
|
||||
if(flValue >= 0.1f && flValue <= 20.0f)
|
||||
if(flValue >= AL_REVERB_MIN_DECAY_TIME &&
|
||||
flValue <= AL_REVERB_MAX_DECAY_TIME)
|
||||
ALEffect->Reverb.DecayTime = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_DECAY_HFRATIO:
|
||||
if(flValue >= 0.1f && flValue <= 2.0f)
|
||||
if(flValue >= AL_REVERB_MIN_DECAY_HFRATIO &&
|
||||
flValue <= AL_REVERB_MAX_DECAY_HFRATIO)
|
||||
ALEffect->Reverb.DecayHFRatio = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_REFLECTIONS_GAIN:
|
||||
if(flValue >= 0.0f && flValue <= 3.16f)
|
||||
if(flValue >= AL_REVERB_MIN_REFLECTIONS_GAIN &&
|
||||
flValue <= AL_REVERB_MAX_REFLECTIONS_GAIN)
|
||||
ALEffect->Reverb.ReflectionsGain = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_REFLECTIONS_DELAY:
|
||||
if(flValue >= 0.0f && flValue <= 0.3f)
|
||||
if(flValue >= AL_REVERB_MIN_REFLECTIONS_DELAY &&
|
||||
flValue <= AL_REVERB_MAX_REFLECTIONS_DELAY)
|
||||
ALEffect->Reverb.ReflectionsDelay = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_LATE_REVERB_GAIN:
|
||||
if(flValue >= 0.0f && flValue <= 10.0f)
|
||||
if(flValue >= AL_REVERB_MIN_LATE_REVERB_GAIN &&
|
||||
flValue <= AL_REVERB_MAX_LATE_REVERB_GAIN)
|
||||
ALEffect->Reverb.LateReverbGain = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_LATE_REVERB_DELAY:
|
||||
if(flValue >= 0.0f && flValue <= 0.1f)
|
||||
if(flValue >= AL_REVERB_MIN_LATE_REVERB_DELAY &&
|
||||
flValue <= AL_REVERB_MAX_LATE_REVERB_DELAY)
|
||||
ALEffect->Reverb.LateReverbDelay = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_AIR_ABSORPTION_GAINHF:
|
||||
if(flValue >= 0.892f && flValue <= 1.0f)
|
||||
if(flValue >= AL_REVERB_MIN_AIR_ABSORPTION_GAINHF &&
|
||||
flValue <= AL_REVERB_MAX_AIR_ABSORPTION_GAINHF)
|
||||
ALEffect->Reverb.AirAbsorptionGainHF = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_REVERB_ROOM_ROLLOFF_FACTOR:
|
||||
if(flValue >= 0.0f && flValue <= 10.0f)
|
||||
if(flValue >= AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR &&
|
||||
flValue <= AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR)
|
||||
ALEffect->Reverb.RoomRolloffFactor = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
@@ -343,6 +575,50 @@ ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_ECHO)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_ECHO_DELAY:
|
||||
if(flValue >= AL_ECHO_MIN_DELAY && flValue <= AL_ECHO_MAX_DELAY)
|
||||
ALEffect->Echo.Delay = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_ECHO_LRDELAY:
|
||||
if(flValue >= AL_ECHO_MIN_LRDELAY && flValue <= AL_ECHO_MAX_LRDELAY)
|
||||
ALEffect->Echo.LRDelay = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_ECHO_DAMPING:
|
||||
if(flValue >= AL_ECHO_MIN_DAMPING && flValue <= AL_ECHO_MAX_DAMPING)
|
||||
ALEffect->Echo.Damping = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_ECHO_FEEDBACK:
|
||||
if(flValue >= AL_ECHO_MIN_FEEDBACK && flValue <= AL_ECHO_MAX_FEEDBACK)
|
||||
ALEffect->Echo.Feedback = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_ECHO_SPREAD:
|
||||
if(flValue >= AL_ECHO_MIN_SPREAD && flValue <= AL_ECHO_MAX_SPREAD)
|
||||
ALEffect->Echo.Spread = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
}
|
||||
@@ -363,7 +639,60 @@ ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
|
||||
{
|
||||
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
|
||||
|
||||
if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
if(ALEffect->type == AL_EFFECT_EAXREVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EAXREVERB_DENSITY:
|
||||
case AL_EAXREVERB_DIFFUSION:
|
||||
case AL_EAXREVERB_GAIN:
|
||||
case AL_EAXREVERB_GAINHF:
|
||||
case AL_EAXREVERB_GAINLF:
|
||||
case AL_EAXREVERB_DECAY_TIME:
|
||||
case AL_EAXREVERB_DECAY_HFRATIO:
|
||||
case AL_EAXREVERB_DECAY_LFRATIO:
|
||||
case AL_EAXREVERB_REFLECTIONS_GAIN:
|
||||
case AL_EAXREVERB_REFLECTIONS_DELAY:
|
||||
case AL_EAXREVERB_LATE_REVERB_GAIN:
|
||||
case AL_EAXREVERB_LATE_REVERB_DELAY:
|
||||
case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
|
||||
case AL_EAXREVERB_ECHO_TIME:
|
||||
case AL_EAXREVERB_ECHO_DEPTH:
|
||||
case AL_EAXREVERB_MODULATION_TIME:
|
||||
case AL_EAXREVERB_MODULATION_DEPTH:
|
||||
case AL_EAXREVERB_HFREFERENCE:
|
||||
case AL_EAXREVERB_LFREFERENCE:
|
||||
case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
|
||||
alEffectf(effect, param, pflValues[0]);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_REFLECTIONS_PAN:
|
||||
if(!isnan(pflValues[0]) && !isnan(pflValues[1]) && !isnan(pflValues[2]))
|
||||
{
|
||||
ALEffect->Reverb.ReflectionsPan[0] = pflValues[0];
|
||||
ALEffect->Reverb.ReflectionsPan[1] = pflValues[1];
|
||||
ALEffect->Reverb.ReflectionsPan[2] = pflValues[2];
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
case AL_EAXREVERB_LATE_REVERB_PAN:
|
||||
if(!isnan(pflValues[0]) && !isnan(pflValues[1]) && !isnan(pflValues[2]))
|
||||
{
|
||||
ALEffect->Reverb.LateReverbPan[0] = pflValues[0];
|
||||
ALEffect->Reverb.LateReverbPan[1] = pflValues[1];
|
||||
ALEffect->Reverb.LateReverbPan[2] = pflValues[2];
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
@@ -387,6 +716,23 @@ ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_ECHO)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_ECHO_DELAY:
|
||||
case AL_ECHO_LRDELAY:
|
||||
case AL_ECHO_DAMPING:
|
||||
case AL_ECHO_FEEDBACK:
|
||||
case AL_ECHO_SPREAD:
|
||||
alEffectf(effect, param, pflValues[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
}
|
||||
@@ -411,6 +757,19 @@ ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
|
||||
{
|
||||
*piValue = ALEffect->type;
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_EAXREVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EAXREVERB_DECAY_HFLIMIT:
|
||||
*piValue = ALEffect->Reverb.DecayHFLimit;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
switch(param)
|
||||
@@ -424,6 +783,15 @@ ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_ECHO)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
}
|
||||
@@ -448,6 +816,19 @@ ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
|
||||
{
|
||||
alGetEffecti(effect, param, piValues);
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_EAXREVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EAXREVERB_DECAY_HFLIMIT:
|
||||
alGetEffecti(effect, param, piValues);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
switch(param)
|
||||
@@ -461,6 +842,15 @@ ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_ECHO)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
}
|
||||
@@ -481,7 +871,96 @@ ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
|
||||
{
|
||||
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
|
||||
|
||||
if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
if(ALEffect->type == AL_EFFECT_EAXREVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EAXREVERB_DENSITY:
|
||||
*pflValue = ALEffect->Reverb.Density;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_DIFFUSION:
|
||||
*pflValue = ALEffect->Reverb.Diffusion;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_GAIN:
|
||||
*pflValue = ALEffect->Reverb.Gain;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_GAINHF:
|
||||
*pflValue = ALEffect->Reverb.GainHF;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_GAINLF:
|
||||
*pflValue = ALEffect->Reverb.GainLF;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_DECAY_TIME:
|
||||
*pflValue = ALEffect->Reverb.DecayTime;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_DECAY_HFRATIO:
|
||||
*pflValue = ALEffect->Reverb.DecayHFRatio;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_DECAY_LFRATIO:
|
||||
*pflValue = ALEffect->Reverb.DecayLFRatio;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_REFLECTIONS_GAIN:
|
||||
*pflValue = ALEffect->Reverb.ReflectionsGain;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_REFLECTIONS_DELAY:
|
||||
*pflValue = ALEffect->Reverb.ReflectionsDelay;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_LATE_REVERB_GAIN:
|
||||
*pflValue = ALEffect->Reverb.LateReverbGain;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_LATE_REVERB_DELAY:
|
||||
*pflValue = ALEffect->Reverb.LateReverbDelay;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
|
||||
*pflValue = ALEffect->Reverb.AirAbsorptionGainHF;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_ECHO_TIME:
|
||||
*pflValue = ALEffect->Reverb.EchoTime;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_ECHO_DEPTH:
|
||||
*pflValue = ALEffect->Reverb.EchoDepth;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_MODULATION_TIME:
|
||||
*pflValue = ALEffect->Reverb.ModulationTime;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_MODULATION_DEPTH:
|
||||
*pflValue = ALEffect->Reverb.ModulationDepth;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_HFREFERENCE:
|
||||
*pflValue = ALEffect->Reverb.HFReference;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_LFREFERENCE:
|
||||
*pflValue = ALEffect->Reverb.LFReference;
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
|
||||
*pflValue = ALEffect->Reverb.RoomRolloffFactor;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
@@ -538,6 +1017,35 @@ ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_ECHO)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_ECHO_DELAY:
|
||||
*pflValue = ALEffect->Echo.Delay;
|
||||
break;
|
||||
|
||||
case AL_ECHO_LRDELAY:
|
||||
*pflValue = ALEffect->Echo.LRDelay;
|
||||
break;
|
||||
|
||||
case AL_ECHO_DAMPING:
|
||||
*pflValue = ALEffect->Echo.Damping;
|
||||
break;
|
||||
|
||||
case AL_ECHO_FEEDBACK:
|
||||
*pflValue = ALEffect->Echo.Feedback;
|
||||
break;
|
||||
|
||||
case AL_ECHO_SPREAD:
|
||||
*pflValue = ALEffect->Echo.Spread;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
}
|
||||
@@ -558,7 +1066,50 @@ ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues
|
||||
{
|
||||
ALeffect *ALEffect = (ALeffect*)ALTHUNK_LOOKUPENTRY(effect);
|
||||
|
||||
if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
if(ALEffect->type == AL_EFFECT_EAXREVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_EAXREVERB_DENSITY:
|
||||
case AL_EAXREVERB_DIFFUSION:
|
||||
case AL_EAXREVERB_GAIN:
|
||||
case AL_EAXREVERB_GAINHF:
|
||||
case AL_EAXREVERB_GAINLF:
|
||||
case AL_EAXREVERB_DECAY_TIME:
|
||||
case AL_EAXREVERB_DECAY_HFRATIO:
|
||||
case AL_EAXREVERB_DECAY_LFRATIO:
|
||||
case AL_EAXREVERB_REFLECTIONS_GAIN:
|
||||
case AL_EAXREVERB_REFLECTIONS_DELAY:
|
||||
case AL_EAXREVERB_LATE_REVERB_GAIN:
|
||||
case AL_EAXREVERB_LATE_REVERB_DELAY:
|
||||
case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
|
||||
case AL_EAXREVERB_ECHO_TIME:
|
||||
case AL_EAXREVERB_ECHO_DEPTH:
|
||||
case AL_EAXREVERB_MODULATION_TIME:
|
||||
case AL_EAXREVERB_MODULATION_DEPTH:
|
||||
case AL_EAXREVERB_HFREFERENCE:
|
||||
case AL_EAXREVERB_LFREFERENCE:
|
||||
case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
|
||||
alGetEffectf(effect, param, pflValues);
|
||||
break;
|
||||
|
||||
case AL_EAXREVERB_REFLECTIONS_PAN:
|
||||
pflValues[0] = ALEffect->Reverb.ReflectionsPan[0];
|
||||
pflValues[1] = ALEffect->Reverb.ReflectionsPan[1];
|
||||
pflValues[2] = ALEffect->Reverb.ReflectionsPan[2];
|
||||
break;
|
||||
case AL_EAXREVERB_LATE_REVERB_PAN:
|
||||
pflValues[0] = ALEffect->Reverb.LateReverbPan[0];
|
||||
pflValues[1] = ALEffect->Reverb.LateReverbPan[1];
|
||||
pflValues[2] = ALEffect->Reverb.LateReverbPan[2];
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_REVERB)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
@@ -582,6 +1133,23 @@ ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(ALEffect->type == AL_EFFECT_ECHO)
|
||||
{
|
||||
switch(param)
|
||||
{
|
||||
case AL_ECHO_DELAY:
|
||||
case AL_ECHO_LRDELAY:
|
||||
case AL_ECHO_DAMPING:
|
||||
case AL_ECHO_FEEDBACK:
|
||||
case AL_ECHO_SPREAD:
|
||||
alGetEffectf(effect, param, pflValues);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
}
|
||||
@@ -617,20 +1185,46 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
|
||||
effect->type = type;
|
||||
switch(type)
|
||||
{
|
||||
/* NOTE: Standard reverb and EAX reverb use the same defaults for the
|
||||
* shared parameters, and EAX's additional parameters default to
|
||||
* values assumed by standard reverb.
|
||||
*/
|
||||
case AL_EFFECT_EAXREVERB:
|
||||
case AL_EFFECT_REVERB:
|
||||
effect->Reverb.Density = 1.0f;
|
||||
effect->Reverb.Diffusion = 1.0f;
|
||||
effect->Reverb.Gain = 0.32f;
|
||||
effect->Reverb.GainHF = 0.89f;
|
||||
effect->Reverb.DecayTime = 1.49f;
|
||||
effect->Reverb.DecayHFRatio = 0.83f;
|
||||
effect->Reverb.ReflectionsGain = 0.05f;
|
||||
effect->Reverb.ReflectionsDelay = 0.007f;
|
||||
effect->Reverb.LateReverbGain = 1.26f;
|
||||
effect->Reverb.LateReverbDelay = 0.011f;
|
||||
effect->Reverb.AirAbsorptionGainHF = 0.994f;
|
||||
effect->Reverb.RoomRolloffFactor = 0.0f;
|
||||
effect->Reverb.DecayHFLimit = AL_TRUE;
|
||||
effect->Reverb.Density = AL_EAXREVERB_DEFAULT_DENSITY;
|
||||
effect->Reverb.Diffusion = AL_EAXREVERB_DEFAULT_DIFFUSION;
|
||||
effect->Reverb.Gain = AL_EAXREVERB_DEFAULT_GAIN;
|
||||
effect->Reverb.GainHF = AL_EAXREVERB_DEFAULT_GAINHF;
|
||||
effect->Reverb.GainLF = AL_EAXREVERB_DEFAULT_GAINLF;
|
||||
effect->Reverb.DecayTime = AL_EAXREVERB_DEFAULT_DECAY_TIME;
|
||||
effect->Reverb.DecayHFRatio = AL_EAXREVERB_DEFAULT_DECAY_HFRATIO;
|
||||
effect->Reverb.DecayLFRatio = AL_EAXREVERB_DEFAULT_DECAY_LFRATIO;
|
||||
effect->Reverb.ReflectionsGain = AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN;
|
||||
effect->Reverb.ReflectionsDelay = AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY;
|
||||
effect->Reverb.ReflectionsPan[0] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ;
|
||||
effect->Reverb.ReflectionsPan[1] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ;
|
||||
effect->Reverb.ReflectionsPan[2] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ;
|
||||
effect->Reverb.LateReverbGain = AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN;
|
||||
effect->Reverb.LateReverbDelay = AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY;
|
||||
effect->Reverb.LateReverbPan[0] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ;
|
||||
effect->Reverb.LateReverbPan[1] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ;
|
||||
effect->Reverb.LateReverbPan[2] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ;
|
||||
effect->Reverb.EchoTime = AL_EAXREVERB_DEFAULT_ECHO_TIME;
|
||||
effect->Reverb.EchoDepth = AL_EAXREVERB_DEFAULT_ECHO_DEPTH;
|
||||
effect->Reverb.ModulationTime = AL_EAXREVERB_DEFAULT_MODULATION_TIME;
|
||||
effect->Reverb.ModulationDepth = AL_EAXREVERB_DEFAULT_MODULATION_DEPTH;
|
||||
effect->Reverb.AirAbsorptionGainHF = AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF;
|
||||
effect->Reverb.HFReference = AL_EAXREVERB_DEFAULT_HFREFERENCE;
|
||||
effect->Reverb.LFReference = AL_EAXREVERB_DEFAULT_LFREFERENCE;
|
||||
effect->Reverb.RoomRolloffFactor = AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR;
|
||||
effect->Reverb.DecayHFLimit = AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT;
|
||||
break;
|
||||
case AL_EFFECT_ECHO:
|
||||
effect->Echo.Delay = AL_ECHO_DEFAULT_DELAY;
|
||||
effect->Echo.LRDelay = AL_ECHO_DEFAULT_LRDELAY;
|
||||
effect->Echo.Damping = AL_ECHO_DEFAULT_DAMPING;
|
||||
effect->Echo.Feedback = AL_ECHO_DEFAULT_FEEDBACK;
|
||||
effect->Echo.Spread = AL_ECHO_DEFAULT_SPREAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+27
-5
@@ -32,7 +32,7 @@
|
||||
#include "alThunk.h"
|
||||
#include "alAuxEffectSlot.h"
|
||||
|
||||
static ALvoid InitSourceParams(ALsource *pSource);
|
||||
static ALvoid InitSourceParams(ALCcontext *Context, ALsource *pSource);
|
||||
static ALboolean GetSourceOffset(ALsource *pSource, ALenum eName, ALfloat *pflOffset, ALuint updateSize);
|
||||
static ALvoid ApplyOffset(ALsource *pSource, ALboolean bUpdateContext);
|
||||
static ALint GetByteOffset(ALsource *pSource);
|
||||
@@ -78,7 +78,7 @@ ALAPI ALvoid ALAPIENTRY alGenSources(ALsizei n,ALuint *sources)
|
||||
sources[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
|
||||
(*list)->source = sources[i];
|
||||
|
||||
InitSourceParams(*list);
|
||||
InitSourceParams(Context, *list);
|
||||
Context->SourceCount++;
|
||||
i++;
|
||||
|
||||
@@ -359,7 +359,7 @@ ALAPI ALvoid ALAPIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue)
|
||||
break;
|
||||
|
||||
case AL_ROOM_ROLLOFF_FACTOR:
|
||||
if (flValue >= 0.0f && flValue <= 1.0f)
|
||||
if (flValue >= 0.0f && flValue <= 10.0f)
|
||||
pSource->RoomRolloffFactor = flValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
@@ -704,6 +704,19 @@ ALAPI ALvoid ALAPIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue)
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
case AL_DISTANCE_MODEL:
|
||||
if(lValue == AL_NONE ||
|
||||
lValue == AL_INVERSE_DISTANCE ||
|
||||
lValue == AL_INVERSE_DISTANCE_CLAMPED ||
|
||||
lValue == AL_LINEAR_DISTANCE ||
|
||||
lValue == AL_LINEAR_DISTANCE_CLAMPED ||
|
||||
lValue == AL_EXPONENT_DISTANCE ||
|
||||
lValue == AL_EXPONENT_DISTANCE_CLAMPED)
|
||||
pSource->DistanceModel = lValue;
|
||||
else
|
||||
alSetError(AL_INVALID_VALUE);
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -819,6 +832,7 @@ ALAPI void ALAPIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plVa
|
||||
case AL_DIRECT_FILTER_GAINHF_AUTO:
|
||||
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
|
||||
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
|
||||
case AL_DISTANCE_MODEL:
|
||||
alSourcei(source, eParam, plValues[0]);
|
||||
break;
|
||||
|
||||
@@ -1212,6 +1226,10 @@ ALAPI ALvoid ALAPIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValu
|
||||
*plValue = (ALint)pSource->DopplerFactor;
|
||||
break;
|
||||
|
||||
case AL_DISTANCE_MODEL:
|
||||
*plValue = pSource->DistanceModel;
|
||||
break;
|
||||
|
||||
default:
|
||||
alSetError(AL_INVALID_ENUM);
|
||||
break;
|
||||
@@ -1326,6 +1344,7 @@ ALAPI void ALAPIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValue
|
||||
case AL_DIRECT_FILTER_GAINHF_AUTO:
|
||||
case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
|
||||
case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
|
||||
case AL_DISTANCE_MODEL:
|
||||
alGetSourcei(source, eParam, plValues);
|
||||
break;
|
||||
|
||||
@@ -1425,7 +1444,8 @@ ALAPI ALvoid ALAPIENTRY alSourcePlayv(ALsizei n, const ALuint *pSourceList)
|
||||
{
|
||||
for(j = 0;j < OUTPUTCHANNELS;j++)
|
||||
pSource->DryGains[j] = 0.0f;
|
||||
pSource->WetGain = 0.0f;
|
||||
for(j = 0;j < MAX_SENDS;j++)
|
||||
pSource->WetGains[j] = 0.0f;
|
||||
|
||||
if (pSource->state != AL_PAUSED)
|
||||
{
|
||||
@@ -1979,7 +1999,7 @@ ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint
|
||||
}
|
||||
|
||||
|
||||
static ALvoid InitSourceParams(ALsource *pSource)
|
||||
static ALvoid InitSourceParams(ALCcontext *Context, ALsource *pSource)
|
||||
{
|
||||
pSource->flInnerAngle = 360.0f;
|
||||
pSource->flOuterAngle = 360.0f;
|
||||
@@ -2010,6 +2030,8 @@ static ALvoid InitSourceParams(ALsource *pSource)
|
||||
pSource->RoomRolloffFactor = 0.0f;
|
||||
pSource->DopplerFactor = 1.0f;
|
||||
|
||||
pSource->DistanceModel = Context->DistanceModel;
|
||||
|
||||
pSource->state = AL_INITIAL;
|
||||
pSource->lSourceType = AL_UNDETERMINED;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "alMain.h"
|
||||
#include "AL/alc.h"
|
||||
#include "alError.h"
|
||||
#include "alSource.h"
|
||||
#include "alState.h"
|
||||
|
||||
static const ALchar alVendor[] = "OpenAL Community";
|
||||
@@ -644,6 +645,7 @@ ALAPI ALvoid ALAPIENTRY alSpeedOfSound(ALfloat flSpeedOfSound)
|
||||
ALAPI ALvoid ALAPIENTRY alDistanceModel(ALenum value)
|
||||
{
|
||||
ALCcontext *Context;
|
||||
ALsource *Source;
|
||||
|
||||
Context=alcGetCurrentContext();
|
||||
if (Context)
|
||||
@@ -660,6 +662,8 @@ 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;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Cross-compiling requires CMake 2.6 or newer. To cross-compile, first modify
|
||||
# this file to set the proper settings and paths. Then use it from CMakeConf/
|
||||
# like:
|
||||
# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt \
|
||||
# -DCMAKE_INSTALL_PREFIX=/usr/mingw32/mingw
|
||||
# If you already have a toolchain file setup, you may use that instead of this
|
||||
# file.
|
||||
|
||||
# the name of the target operating system
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
|
||||
# which compilers to use for C and C++
|
||||
SET(CMAKE_C_COMPILER mingw32-gcc)
|
||||
SET(CMAKE_CXX_COMPILER mingw32-g++)
|
||||
|
||||
# here is the target environment located
|
||||
SET(CMAKE_FIND_ROOT_PATH /usr/mingw32/mingw)
|
||||
|
||||
# adjust the default behaviour of the FIND_XXX() commands:
|
||||
# search headers and libraries in the target environment, search
|
||||
# programs in the host environment
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
+182
-75
@@ -12,96 +12,203 @@
|
||||
# hints and may not be honored (though generally it'll try to get as close as
|
||||
# possible). These are the current available settings:
|
||||
|
||||
format = AL_FORMAT_STEREO16 # Sets the output format. Can be one of:
|
||||
# AL_FORMAT_MONO8 (8-bit mono)
|
||||
# AL_FORMAT_STEREO8 (8-bit stereo)
|
||||
# AL_FORMAT_QUAD8 (8-bit 4-channel)
|
||||
# AL_FORMAT_51CHN8 (8-bit 5.1 output)
|
||||
# AL_FORMAT_61CHN8 (8-bit 6.1 output)
|
||||
# AL_FORMAT_71CHN8 (8-bit 7.1 output)
|
||||
# AL_FORMAT_MONO16 (16-bit mono)
|
||||
# AL_FORMAT_STEREO16 (16-bit stereo)
|
||||
# AL_FORMAT_QUAD16 (16-bit 4-channel)
|
||||
# AL_FORMAT_51CHN16 (16-bit 5.1 output)
|
||||
# AL_FORMAT_61CHN16 (16-bit 6.1 output)
|
||||
# AL_FORMAT_71CHN16 (16-bit 7.1 output)
|
||||
# Default is AL_FORMAT_STEREO16
|
||||
## format:
|
||||
# Sets the output format. Can be one of:
|
||||
# AL_FORMAT_MONO8 (8-bit mono)
|
||||
# AL_FORMAT_STEREO8 (8-bit stereo)
|
||||
# AL_FORMAT_QUAD8 (8-bit 4-channel)
|
||||
# AL_FORMAT_51CHN8 (8-bit 5.1 output)
|
||||
# AL_FORMAT_61CHN8 (8-bit 6.1 output)
|
||||
# AL_FORMAT_71CHN8 (8-bit 7.1 output)
|
||||
# AL_FORMAT_MONO16 (16-bit mono)
|
||||
# AL_FORMAT_STEREO16 (16-bit stereo)
|
||||
# AL_FORMAT_QUAD16 (16-bit 4-channel)
|
||||
# AL_FORMAT_51CHN16 (16-bit 5.1 output)
|
||||
# AL_FORMAT_61CHN16 (16-bit 6.1 output)
|
||||
# AL_FORMAT_71CHN16 (16-bit 7.1 output)
|
||||
#format = AL_FORMAT_STEREO16
|
||||
|
||||
cf_level = 0 # Sets the crossfeed level for stereo output. Valid values are:
|
||||
# 0 - No crossfeed
|
||||
# 1 - Low crossfeed
|
||||
# 2 - Middle crossfeed
|
||||
# 3 - High crossfeed (virtual speakers are closer to itself)
|
||||
# 4 - Low easy crossfeed
|
||||
# 5 - Middle easy crossfeed
|
||||
# 6 - High easy crossfeed
|
||||
# Default is 0. Users of headphones may want to try various
|
||||
# settings. Has no effect on non-stereo modes.
|
||||
## cf_level:
|
||||
# Sets the crossfeed level for stereo output. Valid values are:
|
||||
# 0 - No crossfeed
|
||||
# 1 - Low crossfeed
|
||||
# 2 - Middle crossfeed
|
||||
# 3 - High crossfeed (virtual speakers are closer to itself)
|
||||
# 4 - Low easy crossfeed
|
||||
# 5 - Middle easy crossfeed
|
||||
# 6 - High easy crossfeed
|
||||
# Users of headphones may want to try various settings. Has no effect on non-
|
||||
# stereo modes.
|
||||
#cf_level = 0
|
||||
|
||||
frequency = 44100 # Sets the output frequency. Default is 44100
|
||||
## frequency:
|
||||
# Sets the output frequency.
|
||||
#frequency = 44100
|
||||
|
||||
refresh = 4096 # Sets the buffer size, in frames. Default is 4096. Note that
|
||||
# the actual granularity may or may not be less than this.
|
||||
## refresh:
|
||||
# Sets the buffer size, in frames. Note that the actual granularity may or may
|
||||
# not be less than this.
|
||||
#refresh = 4096
|
||||
|
||||
sources = 256 # Sets the maximum number of allocatable sources. Lower values
|
||||
# may help for systems with apps that try to play more sounds
|
||||
# than the CPU can handle. Default is 256
|
||||
## sources:
|
||||
# Sets the maximum number of allocatable sources. Lower values may help for
|
||||
# systems with apps that try to play more sounds than the CPU can handle.
|
||||
#sources = 256
|
||||
|
||||
stereodup = # Sets whether to duplicate stereo sounds on the rear speakers for
|
||||
# 4+ channel output. This can make stereo sources substantially
|
||||
# louder than mono or even 4+ channel sources, but provides a
|
||||
# "fuller" playback quality. True, yes, on, and non-0 values will
|
||||
# duplicate stereo sources. 0 and anything else will cause stereo
|
||||
# sounds to only play out the front speakers.
|
||||
# Default is false
|
||||
## stereodup:
|
||||
# Sets whether to duplicate stereo sounds on the rear and side speakers for 4+
|
||||
# channel output. This can make stereo sources substantially louder than mono
|
||||
# or even 4+ channel sources, but provides a "fuller" playback quality. True,
|
||||
# yes, on, and non-0 values will duplicate stereo sources. 0 and anything else
|
||||
# will cause stereo sounds to only play out the front speakers.
|
||||
#stereodup = false
|
||||
|
||||
drivers = # Sets the backend driver list order, comma-seperated. Unknown
|
||||
# backends and duplicated names are ignored, and unlisted backends
|
||||
# won't be considered for use. An empty list means the default.
|
||||
# Default is:
|
||||
# alsa,oss,solaris,dsound,winmm,wave
|
||||
## 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
|
||||
|
||||
excludefx = # Sets which effects to exclude, preventing apps from using them.
|
||||
# This can help for apps that try to use effects which are too CPU
|
||||
# intensive for the system to handle. Available effects are:
|
||||
# reverb
|
||||
# Default is empty (all available effects enabled)
|
||||
## excludefx:
|
||||
# Sets which effects to exclude, preventing apps from using them. This can
|
||||
# help for apps that try to use effects which are too CPU intensive for the
|
||||
# system to handle. Available effects are: eaxreverb,reverb,echo
|
||||
#excludefx =
|
||||
|
||||
[alsa] # ALSA backend stuff
|
||||
device = default # Sets the device name for the default playback device.
|
||||
# Default is default
|
||||
## slots:
|
||||
# Sets the maximum number of Auxiliary Effect Slots an app can create. A slot
|
||||
# can use a non-negligible amount of CPU time if an effect is set on it even
|
||||
# if no sources are feeding it, so this may help when apps use more than the
|
||||
# system can handle.
|
||||
#slots = 4
|
||||
|
||||
periods = 0 # Sets the number of update buffers for playback. A value of 0
|
||||
# means auto-select. Default is 0
|
||||
## sends:
|
||||
# Sets the maximum number of auxiliary sends per source. The total number of
|
||||
# sends possible is defined at compile time and thus can not be increased
|
||||
# beyond the default (2).
|
||||
#sends = 2
|
||||
|
||||
capture = default # Sets the device name for the default capture device.
|
||||
# Default is default
|
||||
## layout_STEREO:
|
||||
# Sets the speaker layout when using stereo output. Values are specified in
|
||||
# degrees, where 0 is straight in front, negative goes left, and positive goes
|
||||
# right. The values must define a circular pattern, starting with the back-
|
||||
# left at the most negative, around the front to back-center. Unspecified
|
||||
# speakers will remain at their default position. Available speakers are
|
||||
# front-left(fl) and front-right(fr).
|
||||
#layout_STEREO = fl=-90, fr=90
|
||||
|
||||
mmap = true # Sets whether to try using mmap mode (helps reduce latencies and
|
||||
# CPU consumption). If mmap isn't available, it will automatically
|
||||
# fall back to non-mmap mode. True, yes, on, and non-0 values will
|
||||
# attempt to use mmap. 0 and anything else will force mmap off.
|
||||
# Default is true.
|
||||
## laytout_QUAD:
|
||||
# Sets the speaker layout when using quadriphonic output. Available speakers
|
||||
# are back-left(bl), front-left(fl), front-right(fr), and back-right(br).
|
||||
#layout_QUAD = bl=-135, fl=-45, fr=45, br=135
|
||||
|
||||
[oss] # OSS backend stuff
|
||||
device = /dev/dsp # Sets the device name for OSS output. Default is /dev/dsp
|
||||
## layout_51CHN:
|
||||
# Sets the speaker layout when using 5.1 output. Available speakers are back-
|
||||
# left(bl), front-left(fl), front-center(fc), front-right(fr), and back-
|
||||
# right(br).
|
||||
#layout_51CHN = bl=-110, fl=-30, fc=0, fr=30, br=110
|
||||
|
||||
periods = 4 # Sets the number of update buffers. Default is 4
|
||||
## layout_61CHN:
|
||||
# Sets the speaker layout when using 6.1 output. Available speakers are side-
|
||||
# left(sl), front-left(fl), front-center(fc), front-right(fr), side-right(sr),
|
||||
# and back-center(bc).
|
||||
#layout_61CHN = sl=-90, fl=-30, fc=0, fr=30, sr=90, bc=180
|
||||
|
||||
capture = /dev/dsp # Sets the device name for OSS capture. Default is /dev/dsp
|
||||
## layout_71CHN:
|
||||
# Sets the speaker layout when using 7.1 output. Available speakers are back-
|
||||
# left(bl), side-left(sl), front-left(fl), front-center(fc), front-right(fr),
|
||||
# side-right(sr), and back-right(br).
|
||||
#layout_71CHN = bl=-150, sl=-90, fl=-30, fc=0, fr=30, sr=90, br=150
|
||||
|
||||
[solaris] # Solaris backend stuff
|
||||
device = /dev/audio # Sets the device name for Solaris output. Default is
|
||||
# /dev/audio
|
||||
##
|
||||
## ALSA backend stuff
|
||||
##
|
||||
[alsa]
|
||||
|
||||
[dsound] # DirectSound backend stuff
|
||||
periods = 4 # Sets the number of updates for the output buffer. Default is 4
|
||||
## device:
|
||||
# Sets the device name for the default playback device.
|
||||
#device = default
|
||||
|
||||
[winmm] # Windows Multimedia backend stuff
|
||||
# Nothing yet...
|
||||
## periods:
|
||||
# Sets the number of update buffers for playback. A value of 0 means auto-
|
||||
# select.
|
||||
#periods = 0
|
||||
|
||||
[wave] # Wave File Writer stuff
|
||||
file = # Sets the filename of the wave file to write to. An empty name
|
||||
# prevents the backend from opening, even when explicitly requested.
|
||||
# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION!
|
||||
# Default is empty
|
||||
## capture:
|
||||
# Sets the device name for the default capture device.
|
||||
#capture = default
|
||||
|
||||
## mmap:
|
||||
# Sets whether to try using mmap mode (helps reduce latencies and CPU
|
||||
# consumption). If mmap isn't available, it will automatically fall back to
|
||||
# non-mmap mode. True, yes, on, and non-0 values will attempt to use mmap. 0
|
||||
# and anything else will force mmap off.
|
||||
#mmap = true
|
||||
|
||||
##
|
||||
## OSS backend stuff
|
||||
##
|
||||
[oss]
|
||||
|
||||
## device:
|
||||
# Sets the device name for OSS output.
|
||||
#device = /dev/dsp
|
||||
|
||||
## periods:
|
||||
# Sets the number of update buffers.
|
||||
#periods = 4
|
||||
|
||||
## capture:
|
||||
# Sets the device name for OSS capture.
|
||||
#capture = /dev/dsp
|
||||
|
||||
##
|
||||
## Solaris backend stuff
|
||||
##
|
||||
[solaris]
|
||||
|
||||
## device:
|
||||
# Sets the device name for Solaris output.
|
||||
#device = /dev/audio
|
||||
|
||||
## DirectSound backend stuff
|
||||
[dsound]
|
||||
|
||||
## periods:
|
||||
# Sets the number of updates for the output buffer.
|
||||
#periods = 4
|
||||
|
||||
##
|
||||
## Windows Multimedia backend stuff
|
||||
##
|
||||
[winmm]
|
||||
|
||||
##
|
||||
## PortAudio backend stuff
|
||||
##
|
||||
[port]
|
||||
|
||||
## device:
|
||||
# Sets the device index for output. Negative values will use the default as
|
||||
# given by PortAudio itself.
|
||||
#device = -1
|
||||
|
||||
## periods:
|
||||
# Sets the number of update buffers.
|
||||
#periods = 4
|
||||
|
||||
##
|
||||
## PulseAudio backend stuff
|
||||
##
|
||||
[pulse]
|
||||
|
||||
##
|
||||
## Wave File Writer stuff
|
||||
##
|
||||
[wave]
|
||||
|
||||
## file:
|
||||
# Sets the filename of the wave file to write to. An empty name prevents the
|
||||
# backend from opening, even when explicitly requested.
|
||||
# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION!
|
||||
#file =
|
||||
|
||||
+12
@@ -19,6 +19,12 @@
|
||||
/* Define if we have the Windows Multimedia backend */
|
||||
#cmakedefine HAVE_WINMM
|
||||
|
||||
/* Define if we have the PortAudio backend */
|
||||
#cmakedefine HAVE_PORTAUDIO
|
||||
|
||||
/* Define if we have the PulseAudio backend */
|
||||
#cmakedefine HAVE_PULSEAUDIO
|
||||
|
||||
/* Define if we have dlfcn.h */
|
||||
#cmakedefine HAVE_DLFCN_H
|
||||
|
||||
@@ -28,6 +34,12 @@
|
||||
/* Define if we have the acosf function */
|
||||
#cmakedefine HAVE_ACOSF
|
||||
|
||||
/* Define if we have the atanf function */
|
||||
#cmakedefine HAVE_ATANF
|
||||
|
||||
/* Define if we have the fabsf function */
|
||||
#cmakedefine HAVE_FABSF
|
||||
|
||||
/* Define if we have the strtof function */
|
||||
#cmakedefine HAVE_STRTOF
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ static void printEFXInfo(void)
|
||||
const char *name;
|
||||
} effects[] = {
|
||||
{ AL_EFFECT_EAXREVERB, "EAX Reverb" },
|
||||
{ AL_EFFECT_REVERB, "Standard Reverb" },
|
||||
{ AL_EFFECT_REVERB, "Reverb" },
|
||||
{ AL_EFFECT_CHORUS, "Chorus" },
|
||||
{ AL_EFFECT_DISTORTION, "Distortion" },
|
||||
{ AL_EFFECT_ECHO, "Echo" },
|
||||
|
||||
Reference in New Issue
Block a user