Compare commits

...

94 Commits

Author SHA1 Message Date
Chris Robinson 043fe6edd2 Release 1.8.466 2009-06-07 22:30:08 -07:00
Chris Robinson ef68e5d0ff Protect ring buffer access with the lock 2009-06-07 21:34:05 -07:00
Chris Robinson c6f3a4e062 Move a couple inline functions into the header 2009-06-07 20:16:41 -07:00
Chris Robinson 87ed53c7f6 Don't read deprecated config files 2009-06-07 20:12:01 -07:00
Alam Arias 89e9437b84 add check for _WAVEFORMATEXTENSIBLE_ and define _WIN32_IE before inlcuding any header 2009-06-07 19:43:42 -07:00
Chris Robinson 1454c46b5f Use a thread-safe static inline function for printing 2009-06-07 15:42:15 -07:00
Chris Robinson 0fac1e9115 Store the max number of auxiliary slots in the device 2009-06-07 14:53:22 -07:00
Chris Robinson f3a3358e63 Fix for MSVC
MSVC won't accept zero-sized arrays at the end of structs, if that struct is
used in another struct that's not also at the end. This wastes a float for each
FILTER object
2009-06-06 23:33:53 -07:00
Chris Robinson 3c122b0bef Set an error if effect creation fails 2009-05-31 11:54:49 -07:00
Chris Robinson 7940003d06 Set an error if NaN is given for panning values 2009-05-31 11:34:07 -07:00
Chris Robinson 45b16ff456 Use the generic FILTER object for the master effect filter
Also fix a couple comments
2009-05-30 12:54:53 -07:00
Chris Robinson 9341f4f884 Fixup panning gain calculations
Clamp the panning vector magnitude to 1, and use an energy-reduction method as
the vector magnitude increases (to simulate reverb area occlusion)
2009-05-30 00:32:17 -07:00
Chris Robinson 2c20f26784 Apply slot gain on slot output, not input 2009-05-29 16:51:00 -07:00
Chris Robinson 2a21a449b4 Slot gain changes should have an immediate effect 2009-05-29 13:50:58 -07:00
Chris Robinson 74dc7090fd Don't expose effect-specific structures 2009-05-29 13:30:50 -07:00
Chris Robinson e12ac95d69 Use the MIN/MAX/DEFAULT macros for checking and setting the effect parameters 2009-05-29 12:40:08 -07:00
Chris Robinson 34ea7eba9e Add preliminary support for the EAX Reverb effect
Not all parameters are supported yet, though it is a little more fuctional than
standard reverb
2009-05-29 01:32:54 -07:00
Chris Robinson 6d3ba44f55 Don't update the devicevalues before returning success 2009-05-27 07:02:33 -07:00
Chris Robinson 5a8ad67660 Lock the context before getting the mmap region to update 2009-05-26 14:54:59 -07:00
Chris Robinson f1e442408b Set the correct data size 2009-05-26 14:51:57 -07:00
Chris Robinson a946af4463 Simplify ALSA PCM parameter retrieval 2009-05-26 10:08:27 -07:00
Chris Robinson e01cd92d56 Set avail_min so snd_pcm_wait will wait for the full update to be ready 2009-05-26 10:03:17 -07:00
Chris Robinson 923af8c3a6 Don't update the source's gains in the sample mixing loop
Update copies stored on the stack instead, then update the source after mixing
2009-05-26 09:23:49 -07:00
Chris Robinson ac04cf57fa Make sure _CRT_SECURE_NO_WARNINGS is always defined for MSVC 2009-05-26 06:02:40 -07:00
Chris Robinson 1f6c4e01db Properly fall back to non-mmap capture if the parameters fail 2009-05-25 16:06:03 -07:00
Chris Robinson 04135723a2 Get rid of the ugly ok() macro 2009-05-25 13:07:49 -07:00
Chris Robinson 93fbdb1e6c Redo OSS mixing loop 2009-05-25 12:12:37 -07:00
Chris Robinson c1de15f840 Update in descrete amounts using the update size 2009-05-25 12:01:14 -07:00
Chris Robinson 3be399c555 Do not open pulseaudio if it didn't load 2009-05-19 06:37:22 -07:00
Chris Robinson 1f5453075c Dynamically load PulseAudio 2009-05-19 06:35:12 -07:00
Chris Robinson 33a74f1594 Clear the filter history directly 2009-05-17 22:50:07 -07:00
Chris Robinson e4da1224cb Optionally install the sample configuration file 2009-05-17 22:36:45 -07:00
Chris Robinson 5c2a47620c Reformat the sample config file 2009-05-17 22:24:29 -07:00
Chris Robinson 1bfa7609d2 Make the filter functions global inline, and use it for echo 2009-05-16 23:34:26 -07:00
Chris Robinson 7e8501123a Set some common macros in alu.h 2009-05-16 23:26:39 -07:00
Chris Robinson c447eeb2c7 Use the source reference distance to specify full panning magnitude
Sources that are closer than the specified reference distance will not pan to
full magnitude, thus providing a smoother transition as it moves around near
the listener
2009-05-16 03:54:16 -07:00
Chris Robinson ad19cea6e0 Make sure DSSPEAKER_5POINT1 is defined 2009-05-14 05:24:18 -07:00
Chris Robinson 0ce29863e3 Prevent spawning PulseAudio if it's not already running 2009-05-06 00:19:35 -07:00
Chris Robinson 7a7a4844f4 Make the filter history buffer size flexible
This lets the filter history buffer be as big as needed for a given use, so
that it can have a size large enough for the more demanding cases, but not be
wasteful for lesser-demanding cases, while not incuring the overhead of an
added pointer indirection
2009-04-16 05:43:09 -07:00
Chris Robinson a2adbb1ab5 Add a PulseAudio backend 2009-04-16 05:17:42 -07:00
Chris Robinson a97fc792d8 Increase the default maximum number of sends to 2 2009-04-14 22:18:47 -07:00
Chris Robinson e9a6a1d6f5 Use a 2-pole filter for the wet path low-pass filter
This should help keep CPU use from increasing a lot when the number of sends
increases. Also changes the function names to reflect the difference
2009-04-14 22:04:18 -07:00
Chris Robinson f245f0ef87 Make the number of source sends variable
The highest value is clamped to MAX_SENDS
2009-04-13 20:33:41 -07:00
Chris Robinson a30f431b63 Reduce the number of send loops 2009-04-13 02:50:40 -07:00
Chris Robinson 58f48f20e2 Rename Standard Reverb to Reverb 2009-04-13 02:01:21 -07:00
Chris Robinson ee1b02b709 Fix comment regarding the 3rd echo tap 2009-04-12 18:54:26 -07:00
Chris Robinson 55c790c9ff Add the Echo effect 2009-04-12 16:01:10 -07:00
Chris Robinson 65b69f3308 Fix air absorption 2009-04-11 20:27:55 -07:00
Chris Robinson c67fbd72dd Pay attention to the MAX_SENDS value 2009-04-11 20:04:46 -07:00
Chris Robinson 30f57d0824 Make auxiliary effect slot count configurable 2009-04-11 18:16:05 -07:00
Chris Robinson 1c54018111 Move the WetBuffer into the effect slot object
This should make it easier to support multiple slots
2009-04-11 17:04:55 -07:00
Chris Robinson e80e1b6d9f Use LIB_SUFFIX when creating the default lib install dir
Thanks to Hanno Böck for pointing this out
2009-04-07 12:11:41 -07:00
Chris Robinson 437f00d6de Add missing comment markers 2009-04-07 11:41:41 -07:00
Chris Robinson fc6d6b1601 Use the square of the values when calculating the density gain 2009-03-21 10:42:42 -07:00
Chris Robinson 9306e36d52 Make sure M_PI is defined for reverb 2009-03-15 23:14:40 -07:00
Chris Robinson 61122a5093 Release 1.7.411 2009-03-14 22:24:59 -07:00
Chris Robinson a8a4ff8af1 Constify some parameters 2009-03-13 23:08:15 -07:00
Chris Robinson 8a857c35ee Calculate filter coefficients in aluMixData 2009-03-13 22:58:54 -07:00
Chris Robinson 89ddd7d8e5 Don't modify the device struct until playback succesfully starts 2009-03-13 22:16:01 -07:00
Chris Robinson 8d0c4ccb3b The room rolloff factor can go up to 10 2009-03-13 02:12:45 -07:00
Chris Robinson 8ee47d5573 Dynamically load dsound when possible 2009-03-10 02:46:42 -07:00
Chris Robinson 9e88011417 Add a cast for setting a dummy pointer value 2009-03-10 02:20:05 -07:00
Chris Robinson f8949ee7a1 Always add the default ALSA device even if no cards are present 2009-03-10 01:46:51 -07:00
Chris Robinson 62aa2d0ba7 Only expose the default ALSA device in standard enumeration 2009-03-10 01:28:01 -07:00
Chris Robinson ace047d625 Append the card and device indices to the ALSA device strings 2009-03-10 01:21:42 -07:00
Chris Robinson d6277db209 Fix alsoftrc configuration sample comments 2009-03-10 01:08:03 -07:00
Chris Robinson 7ebb28327f Remove the SDL backend 2009-03-10 01:03:39 -07:00
Chris Robinson 86931cbde4 Add a PortAudio backend 2009-03-10 00:55:29 -07:00
Chris Robinson 6d7be151dc Remove the unneeded path from the cross-compiler commands 2009-03-06 20:09:44 -08:00
Chris Robinson 07227b9806 Use a modified reverb model that obeys the reverb parameters better 2009-03-02 18:48:23 -08:00
Chris Robinson 8348d719cd Clamp gain of multichannel sources 2009-02-10 15:15:49 -08:00
Chris Robinson 0fcefd865b Install the pkgconfig file to the correct directory 2009-02-10 14:39:48 -08:00
Chris Robinson 57c2e9b5f8 Include assert.h for assert() 2009-02-02 11:18:33 -08:00
Chris Robinson 7d7fc39035 Use calculated distance from reference for air absorption 2009-01-30 10:56:25 -08:00
Chris Robinson 351105b3df Fix incorrect comment 2009-01-30 10:53:09 -08:00
Chris Robinson cbfc33215b Use M_PI since it is sure to be defined 2009-01-27 07:11:58 -08:00
Chris Robinson 5a93b56673 Fix ignored return value warning 2009-01-26 08:10:05 -08:00
Chris Robinson 1f4c69c17a Use a matrix for up- and down-mixing channels 2009-01-25 22:11:07 -08:00
Chris Robinson f5b19fad20 Duplicate stereo onto the side channels as well as the back 2009-01-25 19:54:50 -08:00
Chris Robinson bc60818e9a Don't read stereo layout when output is mono 2009-01-25 19:33:52 -08:00
Chris Robinson f82c88f016 Add options for user-configurable speaker arrangements 2009-01-25 19:20:47 -08:00
Chris Robinson 98e86decad 6.1 uses front- and back-center, not left- and right-back channels 2009-01-24 15:13:14 -08:00
Chris Robinson aaf2c0ebd4 Seperate mixing loops depending on source channel configuration 2009-01-24 13:57:01 -08:00
Chris Robinson 778b74cae1 Reimplement panning using lookup tables, based on a patch by Christian Borss
This allows speaker positions to be specified by discrete angles around the
listener, providing more flexibility and configurability in placement.
Additional patches to take advantage of this are forthcoming.
2009-01-24 10:38:04 -08:00
Chris Robinson 43ee1edd97 Properly capitalize the libname in Win32 2009-01-10 21:23:53 -08:00
Chris Robinson dd7e23740b Remove XCOMPILEWIN32 option in favor of CMake 2.6's cross-compiling caps 2008-12-12 11:19:38 -08:00
Chris Robinson 1acd6da745 Search for SDL.h in addition to SDL/SDL.h 2008-12-12 11:09:23 -08:00
Chris Robinson 3056f91ec5 Apply the dry filter to multi-channel sources
Unlike mono sources, they use 2 chained one-pole filters instead of 4
2008-12-10 11:54:13 -08:00
Chris Robinson ed03570e1a Fix some CMake checks 2008-12-07 02:20:17 -08:00
Chris Robinson 2ec0e48d06 Protect playback device opening with a mutex lock 2008-12-07 01:07:54 -08:00
Chris Robinson 8b54d59b8c Add an SDL backend 2008-12-07 01:05:39 -08:00
Chris Robinson f6a4dbabdd Add cast for setting a dummy pointer value 2008-12-06 12:17:29 -08:00
Chris Robinson a71c291bcb Let CMAKE_DEBUG_POSTFIX be exposed for graphical CMake front-ends 2008-12-02 02:37:51 -08:00
Chris Robinson 55b9ccc2de Implement AL_EXTX_source_distance_model
As with other EXTX extensions, this is subject to change and removal as the
spec gets worked on
2008-11-25 18:56:10 -08:00
29 changed files with 3975 additions and 1138 deletions
+37 -15
View File
@@ -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)
{
+682 -426
View File
File diff suppressed because it is too large Load Diff
+5 -17
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+24 -25
View File
@@ -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
View File
@@ -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);
}
+595
View File
@@ -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
View File
@@ -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
View File
@@ -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!")
+21 -2
View File
@@ -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
View File
@@ -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;
+39 -1
View File
@@ -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
View File
@@ -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;
-26
View File
@@ -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
+5 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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));
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+4
View File
@@ -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:
+24
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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" },