aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c248
-rw-r--r--Alc/loopback.c76
-rw-r--r--CMakeLists.txt1
-rw-r--r--OpenAL32/Include/alMain.h57
4 files changed, 360 insertions, 22 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 6bdcc663..22272a36 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -77,6 +77,9 @@ static BackendInfo BackendList[] = {
{ NULL, NULL, NULL, NULL, EmptyFuncs }
};
+static BackendInfo BackendLoopback = {
+ "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs
+};
#undef EmptyFuncs
///////////////////////////////////////////////////////
@@ -124,6 +127,10 @@ static const ALCfunction alcFunctions[] = {
{ "alcSetThreadContext", (ALCvoid *) alcSetThreadContext },
{ "alcGetThreadContext", (ALCvoid *) alcGetThreadContext },
+ { "alcLoopbackOpenDevice", (ALCvoid *) alcLoopbackOpenDevice },
+ { "alcIsRenderFormatSupported", (ALCvoid *) alcIsRenderFormatSupported},
+ { "alcRenderSamples", (ALCvoid *) alcRenderSamples },
+
{ "alEnable", (ALCvoid *) alEnable },
{ "alDisable", (ALCvoid *) alDisable },
{ "alIsEnabled", (ALCvoid *) alIsEnabled },
@@ -494,6 +501,7 @@ static void alc_init(void)
for(i = 0;BackendList[i].Init;i++)
BackendList[i].Init(&BackendList[i].Funcs);
+ BackendLoopback.Init(&BackendLoopback.Funcs);
str = GetConfigValue(NULL, "excludefx", "");
if(str[0])
@@ -538,6 +546,7 @@ static void alc_deinit(void)
for(i = 0;BackendList[i].Deinit;i++)
BackendList[i].Deinit();
+ BackendLoopback.Deinit();
tls_delete(LocalContext);
@@ -890,6 +899,41 @@ ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans,
return AL_FALSE;
}
+static ALboolean IsValidType(ALenum type)
+{
+ switch(type)
+ {
+ case AL_BYTE:
+ case AL_UNSIGNED_BYTE:
+ case AL_SHORT:
+ case AL_UNSIGNED_SHORT:
+ case AL_INT:
+ case AL_UNSIGNED_INT:
+ case AL_FLOAT:
+ case AL_DOUBLE:
+ case AL_MULAW:
+ case AL_IMA4:
+ return AL_TRUE;
+ }
+ return AL_FALSE;
+}
+
+static ALboolean IsValidChannels(ALenum channels)
+{
+ switch(channels)
+ {
+ case AL_MONO:
+ case AL_STEREO:
+ case AL_REAR:
+ case AL_QUAD:
+ case AL_5POINT1:
+ case AL_6POINT1:
+ case AL_7POINT1:
+ return AL_TRUE;
+ }
+ return AL_FALSE;
+}
+
/*
IsDevice
@@ -952,6 +996,8 @@ ALCvoid alcSetError(ALCdevice *device, ALenum errorCode)
static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
ALCuint freq, numMono, numStereo, numSends;
+ enum DevFmtChannels schans;
+ enum DevFmtType stype;
ALboolean running;
ALuint oldRate;
ALuint attrIdx;
@@ -974,6 +1020,8 @@ static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
}
freq = device->Frequency;
+ schans = device->FmtChans;
+ stype = device->FmtType;
numMono = device->NumMonoSources;
numStereo = device->NumStereoSources;
numSends = device->NumAuxSends;
@@ -981,12 +1029,47 @@ static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
attrIdx = 0;
while(attrList[attrIdx])
{
- if(attrList[attrIdx] == ALC_FREQUENCY &&
- !ConfigValueExists(NULL, "frequency"))
+ if(attrList[attrIdx] == ALC_FORMAT_CHANNELS &&
+ device->IsLoopbackDevice)
{
- freq = attrList[attrIdx + 1];
- if(freq < 8000)
- freq = 8000;
+ ALCint val = attrList[attrIdx + 1];
+ if(!IsValidChannels(val) || !ChannelsFromDevFmt(val))
+ {
+ alcSetError(device, ALC_INVALID_VALUE);
+ return ALC_FALSE;
+ }
+ schans = val;
+ }
+
+ if(attrList[attrIdx] == ALC_FORMAT_TYPE &&
+ device->IsLoopbackDevice)
+ {
+ ALCint val = attrList[attrIdx + 1];
+ if(!IsValidType(val) || !BytesFromDevFmt(val))
+ {
+ alcSetError(device, ALC_INVALID_VALUE);
+ return ALC_FALSE;
+ }
+ stype = val;
+ }
+
+ if(attrList[attrIdx] == ALC_FREQUENCY)
+ {
+ if(device->IsLoopbackDevice)
+ {
+ freq = attrList[attrIdx + 1];
+ if(freq < 8000)
+ {
+ alcSetError(device, ALC_INVALID_VALUE);
+ return ALC_FALSE;
+ }
+ }
+ else if(!ConfigValueExists(NULL, "frequency"))
+ {
+ freq = attrList[attrIdx + 1];
+ if(freq < 8000)
+ freq = 8000;
+ }
}
if(attrList[attrIdx] == ALC_STEREO_SOURCES)
@@ -1013,6 +1096,8 @@ static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
device->Frequency;
device->Frequency = freq;
+ device->FmtChans = schans;
+ device->FmtType = stype;
device->NumMonoSources = numMono;
device->NumStereoSources = numStereo;
device->NumAuxSends = numSends;
@@ -1235,6 +1320,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName,
//Validate device
device->Connected = ALC_TRUE;
device->IsCaptureDevice = AL_TRUE;
+ device->IsLoopbackDevice = AL_FALSE;
device->szDeviceName = NULL;
@@ -1582,11 +1668,22 @@ ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsi
data[i++] = ALC_FREQUENCY;
data[i++] = device->Frequency;
- data[i++] = ALC_REFRESH;
- data[i++] = device->Frequency / device->UpdateSize;
+ if(!device->IsLoopbackDevice)
+ {
+ data[i++] = ALC_REFRESH;
+ data[i++] = device->Frequency / device->UpdateSize;
- data[i++] = ALC_SYNC;
- data[i++] = ALC_FALSE;
+ data[i++] = ALC_SYNC;
+ data[i++] = ALC_FALSE;
+ }
+ else
+ {
+ data[i++] = ALC_FORMAT_CHANNELS;
+ data[i++] = device->FmtChans;
+
+ data[i++] = ALC_FORMAT_TYPE;
+ data[i++] = device->FmtType;
+ }
data[i++] = ALC_MONO_SOURCES;
data[i++] = device->NumMonoSources;
@@ -1610,19 +1707,33 @@ ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsi
break;
case ALC_REFRESH:
- if(!IsDevice(device))
+ if(!IsDevice(device) || device->IsLoopbackDevice)
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = device->Frequency / device->UpdateSize;
break;
case ALC_SYNC:
- if(!IsDevice(device))
+ if(!IsDevice(device) || device->IsLoopbackDevice)
alcSetError(device, ALC_INVALID_DEVICE);
else
*data = ALC_FALSE;
break;
+ case ALC_FORMAT_CHANNELS:
+ if(!IsDevice(device) || !device->IsLoopbackDevice)
+ alcSetError(device, ALC_INVALID_DEVICE);
+ else
+ *data = device->FmtChans;
+ break;
+
+ case ALC_FORMAT_TYPE:
+ if(!IsDevice(device) || !device->IsLoopbackDevice)
+ alcSetError(device, ALC_INVALID_DEVICE);
+ else
+ *data = device->FmtType;
+ break;
+
case ALC_MONO_SOURCES:
if(!IsDevice(device))
alcSetError(device, ALC_INVALID_DEVICE);
@@ -2130,6 +2241,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
//Validate device
device->Connected = ALC_TRUE;
device->IsCaptureDevice = AL_FALSE;
+ device->IsLoopbackDevice = AL_FALSE;
device->LastError = ALC_NO_ERROR;
device->Bs2b = NULL;
@@ -2304,6 +2416,120 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice)
}
+ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDevice(void)
+{
+ ALCdevice *device;
+
+ device = calloc(1, sizeof(ALCdevice));
+ if(!device)
+ {
+ alcSetError(NULL, ALC_OUT_OF_MEMORY);
+ return NULL;
+ }
+
+ //Validate device
+ device->Connected = ALC_TRUE;
+ device->IsCaptureDevice = AL_FALSE;
+ device->IsLoopbackDevice = AL_TRUE;
+ device->LastError = ALC_NO_ERROR;
+
+ device->Bs2b = NULL;
+ device->szDeviceName = NULL;
+
+ device->Contexts = NULL;
+ device->NumContexts = 0;
+
+ InitUIntMap(&device->BufferMap);
+ InitUIntMap(&device->EffectMap);
+ InitUIntMap(&device->FilterMap);
+ InitUIntMap(&device->DatabufferMap);
+
+ //Set output format
+ device->Frequency = 44100;
+ device->FmtChans = DevFmtStereo;
+ device->FmtType = DevFmtShort;
+
+ device->NumUpdates = 0;
+ device->UpdateSize = 0;
+
+ device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
+ if((ALint)device->MaxNoOfSources <= 0)
+ device->MaxNoOfSources = 256;
+
+ device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
+ if((ALint)device->AuxiliaryEffectSlotMax <= 0)
+ device->AuxiliaryEffectSlotMax = 4;
+
+ device->NumStereoSources = 1;
+ device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources;
+
+ device->NumAuxSends = GetConfigValueInt(NULL, "sends", 1);
+ if(device->NumAuxSends > MAX_SENDS)
+ device->NumAuxSends = MAX_SENDS;
+
+ device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
+
+ device->DuplicateStereo = GetConfigValueBool(NULL, "stereodup", 1);
+
+ device->HeadDampen = 0.0f;
+
+ // Open the "backend"
+ SuspendContext(NULL);
+ device->Funcs = &BackendLoopback.Funcs;
+ ALCdevice_OpenPlayback(device, "Loopback");
+
+ device->next = g_pDeviceList;
+ g_pDeviceList = device;
+ g_ulDeviceCount++;
+ ProcessContext(NULL);
+
+ return device;
+}
+
+ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupported(ALCdevice *device, ALCsizei freq, ALenum channels, ALenum type)
+{
+ if(!IsDevice(device) || !device->IsLoopbackDevice)
+ {
+ alcSetError(device, ALC_INVALID_DEVICE);
+ return ALC_FALSE;
+ }
+
+ if(freq < 8000)
+ {
+ if(freq <= 0)
+ alcSetError(device, ALC_INVALID_VALUE);
+ return ALC_FALSE;
+ }
+
+ if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
+ {
+ alcSetError(device, ALC_INVALID_ENUM);
+ return ALC_FALSE;
+ }
+
+ if((type == DevFmtByte || type == DevFmtUByte || type == DevFmtShort ||
+ type == DevFmtUShort || type == DevFmtFloat) &&
+ (channels == DevFmtMono || channels == DevFmtStereo ||
+ channels == DevFmtQuad || channels == DevFmtX51 ||
+ channels == DevFmtX61 || channels == DevFmtX71))
+ return ALC_TRUE;
+
+ return ALC_FALSE;
+}
+
+ALC_API void ALC_APIENTRY alcRenderSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
+{
+ SuspendContext(NULL);
+ if(!IsDevice(device) || !device->IsLoopbackDevice)
+ alcSetError(device, ALC_INVALID_DEVICE);
+ else if(samples < 0)
+ alcSetError(device, ALC_INVALID_VALUE);
+ else
+ aluMixData(device, buffer, samples);
+ ProcessContext(NULL);
+}
+
+
static void ReleaseALC(void)
{
free(alcDeviceList); alcDeviceList = NULL;
diff --git a/Alc/loopback.c b/Alc/loopback.c
new file mode 100644
index 00000000..036e72c1
--- /dev/null
+++ b/Alc/loopback.c
@@ -0,0 +1,76 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 2011 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 <stdlib.h>
+#include "alMain.h"
+#include "AL/al.h"
+#include "AL/alc.h"
+
+
+static ALCboolean loopback_open_playback(ALCdevice *device, const ALCchar *deviceName)
+{
+ device->szDeviceName = strdup(deviceName);
+ return ALC_TRUE;
+}
+
+static void loopback_close_playback(ALCdevice *device)
+{
+ (void)device;
+}
+
+static ALCboolean loopback_reset_playback(ALCdevice *device)
+{
+ SetDefaultWFXChannelOrder(device);
+ return ALC_TRUE;
+}
+
+static void loopback_stop_playback(ALCdevice *device)
+{
+ (void)device;
+}
+
+static BackendFuncs loopback_funcs = {
+ loopback_open_playback,
+ loopback_close_playback,
+ loopback_reset_playback,
+ loopback_stop_playback,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+void alc_loopback_init(BackendFuncs *func_list)
+{
+ *func_list = loopback_funcs;
+}
+
+void alc_loopback_deinit(void)
+{
+}
+
+void alc_loopback_probe(int type)
+{
+ (void)type;
+}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 44f9ea84..2cd7aafa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -327,6 +327,7 @@ SET(ALC_OBJS Alc/ALc.c
Alc/bs2b.c
Alc/mixer.c
Alc/panning.c
+ Alc/loopback.c
Alc/null.c
)
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 02153a86..68e3e372 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -13,6 +13,37 @@
#include "AL/alc.h"
#include "AL/alext.h"
+#ifndef ALC_SOFT_device_loopback
+#define ALC_SOFT_device_loopback 1
+#define AL_BYTE 1
+#define AL_UNSIGNED_BYTE 2
+#define AL_SHORT 3
+#define AL_UNSIGNED_SHORT 4
+#define AL_INT 5
+#define AL_UNSIGNED_INT 6
+#define AL_FLOAT 7
+#define AL_DOUBLE 8
+#define AL_MULAW 9
+#define AL_IMA4 10
+#define AL_MONO 1
+#define AL_STEREO 2
+#define AL_REAR 3
+#define AL_QUAD 4
+#define AL_5POINT1 5 /* (WFX order) */
+#define AL_6POINT1 6 /* (WFX order) */
+#define AL_7POINT1 7 /* (WFX order) */
+#define ALC_FORMAT_CHANNELS 0x1990
+#define ALC_FORMAT_TYPE 0x1991
+typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICE)(void);
+typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTED)(ALCdevice *device, ALCsizei freq, ALenum channels, ALenum type);
+typedef void (ALC_APIENTRY*LPALCRENDERSAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
+#ifdef AL_ALEXT_PROTOTYPES
+ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDevice(void);
+ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupported(ALCdevice *device, ALCsizei freq, ALenum channels, ALenum type);
+ALC_API void ALC_APIENTRY alcRenderSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
+#endif
+#endif
+
#ifndef AL_EXT_sample_buffer_object
#define AL_EXT_sample_buffer_object 1
typedef ptrdiff_t ALintptrEXT;
@@ -294,6 +325,9 @@ void alc_pulse_probe(int type);
void alc_null_init(BackendFuncs *func_list);
void alc_null_deinit(void);
void alc_null_probe(int type);
+void alc_loopback_init(BackendFuncs *func_list);
+void alc_loopback_deinit(void);
+void alc_loopback_probe(int type);
typedef struct UIntMap {
@@ -313,19 +347,19 @@ ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key);
/* Device formats */
enum DevFmtType {
- DevFmtByte, /* AL_BYTE */
- DevFmtUByte, /* AL_UNSIGNED_BYTE */
- DevFmtShort, /* AL_SHORT */
- DevFmtUShort, /* AL_UNSIGNED_SHORT */
- DevFmtFloat, /* AL_FLOAT */
+ DevFmtByte = AL_BYTE,
+ DevFmtUByte = AL_UNSIGNED_BYTE,
+ DevFmtShort = AL_SHORT,
+ DevFmtUShort = AL_UNSIGNED_SHORT,
+ DevFmtFloat = AL_FLOAT
};
enum DevFmtChannels {
- DevFmtMono, /* AL_MONO */
- DevFmtStereo, /* AL_STEREO */
- DevFmtQuad, /* AL_QUAD */
- DevFmtX51, /* AL_5POINT1 */
- DevFmtX61, /* AL_6POINT1 */
- DevFmtX71, /* AL_7POINT1 */
+ DevFmtMono = AL_MONO,
+ DevFmtStereo = AL_STEREO,
+ DevFmtQuad = AL_QUAD,
+ DevFmtX51 = AL_5POINT1,
+ DevFmtX61 = AL_6POINT1,
+ DevFmtX71 = AL_7POINT1
};
ALuint BytesFromDevFmt(enum DevFmtType type);
@@ -341,6 +375,7 @@ struct ALCdevice_struct
{
ALCboolean Connected;
ALboolean IsCaptureDevice;
+ ALboolean IsLoopbackDevice;
ALuint Frequency;
ALuint UpdateSize;