aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml26
-rw-r--r--Alc/ALc.c8
-rw-r--r--Alc/ALu.c31
-rw-r--r--Alc/alconfig.c4
-rw-r--r--Alc/alconfig.h8
-rw-r--r--Alc/ambdec.c566
-rw-r--r--Alc/ambdec.cpp425
-rw-r--r--Alc/ambdec.h27
-rw-r--r--Alc/backends/alsa.c2
-rw-r--r--Alc/backends/dsound.cpp (renamed from Alc/backends/dsound.c)568
-rw-r--r--Alc/backends/jack.c6
-rw-r--r--Alc/backends/portaudio.c2
-rw-r--r--Alc/backends/pulseaudio.cpp (renamed from Alc/backends/pulseaudio.c)1304
-rw-r--r--Alc/backends/wasapi.cpp (renamed from Alc/backends/wasapi.c)1245
-rw-r--r--Alc/bformatdec.cpp (renamed from Alc/bformatdec.c)150
-rw-r--r--Alc/bformatdec.h19
-rw-r--r--Alc/bs2b.c2
-rw-r--r--Alc/compat.h201
-rw-r--r--Alc/converter.c12
-rw-r--r--Alc/converter.h4
-rw-r--r--Alc/effects/autowah.c4
-rw-r--r--Alc/effects/chorus.c10
-rw-r--r--Alc/effects/compressor.c4
-rw-r--r--Alc/effects/dedicated.c4
-rw-r--r--Alc/effects/distortion.c6
-rw-r--r--Alc/effects/echo.c6
-rw-r--r--Alc/effects/equalizer.c6
-rw-r--r--Alc/effects/fshifter.c6
-rw-r--r--Alc/effects/modulator.c8
-rw-r--r--Alc/effects/null.c6
-rw-r--r--Alc/effects/pshifter.c6
-rw-r--r--Alc/effects/reverb.c36
-rw-r--r--Alc/filters/defs.h4
-rw-r--r--Alc/filters/filter.c4
-rw-r--r--Alc/filters/nfc.c6
-rw-r--r--Alc/filters/nfc.h6
-rw-r--r--Alc/filters/splitter.cpp (renamed from Alc/filters/splitter.c)4
-rw-r--r--Alc/filters/splitter.h11
-rw-r--r--Alc/helpers.c2
-rw-r--r--Alc/hrtf.c8
-rw-r--r--Alc/hrtf.h12
-rw-r--r--Alc/logging.h4
-rw-r--r--Alc/mastering.c49
-rw-r--r--Alc/mastering.h2
-rw-r--r--Alc/mixer/defs.h68
-rw-r--r--Alc/mixer/hrtf_inc.c12
-rw-r--r--Alc/mixer/mixer_c.c24
-rw-r--r--Alc/mixer/mixer_neon.c16
-rw-r--r--Alc/mixer/mixer_sse.c12
-rw-r--r--Alc/mixer/mixer_sse2.c4
-rw-r--r--Alc/mixer/mixer_sse41.c4
-rw-r--r--Alc/mixvoice.c8
-rw-r--r--Alc/panning.cpp (renamed from Alc/panning.c)66
-rw-r--r--Alc/polymorphism.h17
-rw-r--r--Alc/uhjfilter.cpp (renamed from Alc/uhjfilter.c)12
-rw-r--r--Alc/uhjfilter.h10
-rw-r--r--Alc/vector.h32
-rw-r--r--CMakeLists.txt117
-rw-r--r--OpenAL32/Include/alAuxEffectSlot.h4
-rw-r--r--OpenAL32/Include/alMain.h36
-rw-r--r--OpenAL32/Include/alu.h24
-rw-r--r--OpenAL32/Include/bs2b.h2
-rw-r--r--OpenAL32/Include/sample_cvt.h8
-rw-r--r--OpenAL32/alAuxEffectSlot.c4
-rw-r--r--OpenAL32/alBuffer.cpp (renamed from OpenAL32/alBuffer.c)1385
-rw-r--r--OpenAL32/alEffect.c4
-rw-r--r--OpenAL32/alFilter.c4
-rw-r--r--OpenAL32/alSource.c60
-rw-r--r--appveyor.yml4
-rw-r--r--common/align.h7
-rw-r--r--common/atomic.h62
-rw-r--r--common/bool.h2
-rw-r--r--common/math_defs.h9
-rw-r--r--common/static_assert.h2
-rw-r--r--common/threads.c35
-rw-r--r--common/threads.h69
-rw-r--r--common/uintmap.c6
-rw-r--r--config.h.in3
-rw-r--r--examples/alrecord.c10
-rw-r--r--router/al.cpp (renamed from router/al.c)26
-rw-r--r--router/alc.cpp (renamed from router/alc.c)501
-rw-r--r--router/router.cpp (renamed from router/router.c)244
-rw-r--r--router/router.h269
-rw-r--r--utils/alsoft-config/mainwindow.cpp2
-rw-r--r--utils/makehrtf.c2
85 files changed, 4076 insertions, 3934 deletions
diff --git a/.travis.yml b/.travis.yml
index 426eef40..e24ed7d8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@ language: c
matrix:
include:
- os: linux
- dist: trusty
+ dist: xenial
- os: linux
dist: trusty
env:
@@ -24,17 +24,18 @@ install:
fi
- >
if [[ "${TRAVIS_OS_NAME}" == "linux" && "${BUILD_ANDROID}" == "true" ]]; then
- curl -o ~/android-ndk.zip https://dl.google.com/android/repository/android-ndk-r15-linux-x86_64.zip
+ curl -o ~/android-ndk.zip https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip
unzip -q ~/android-ndk.zip -d ~ \
- 'android-ndk-r15/build/cmake/*' \
- 'android-ndk-r15/build/core/toolchains/arm-linux-androideabi-*/*' \
- 'android-ndk-r15/platforms/android-14/arch-arm/*' \
- 'android-ndk-r15/source.properties' \
- 'android-ndk-r15/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/*' \
- 'android-ndk-r15/sources/cxx-stl/gnu-libstdc++/4.9/include/*' \
- 'android-ndk-r15/sysroot/*' \
- 'android-ndk-r15/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/*' \
- 'android-ndk-r15/toolchains/llvm/prebuilt/linux-x86_64/*'
+ 'android-ndk-r16b/build/cmake/*' \
+ 'android-ndk-r16b/build/core/toolchains/arm-linux-androideabi-*/*' \
+ 'android-ndk-r16b/platforms/android-14/arch-arm/*' \
+ 'android-ndk-r16b/source.properties' \
+ 'android-ndk-r16b/sources/android/support/include/*' \
+ 'android-ndk-r16b/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/*' \
+ 'android-ndk-r16b/sources/cxx-stl/llvm-libc++/include/*' \
+ 'android-ndk-r16b/sysroot/*' \
+ 'android-ndk-r16b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/*' \
+ 'android-ndk-r16b/toolchains/llvm/prebuilt/linux-x86_64/*'
fi
script:
- >
@@ -51,7 +52,8 @@ script:
- >
if [[ "${TRAVIS_OS_NAME}" == "linux" && "${BUILD_ANDROID}" == "true" ]]; then
cmake \
- -DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r15/build/cmake/android.toolchain.cmake \
+ -DANDROID_STL=c++_shared \
+ -DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r16b/build/cmake/android.toolchain.cmake \
-DALSOFT_REQUIRE_OPENSL=ON \
-DALSOFT_EMBED_HRTF_DATA=YES \
.
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 8bf2e1da..7d28b976 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1566,6 +1566,14 @@ void SetDefaultChannelOrder(ALCdevice *device)
extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan);
extern inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan);
+/* NOTE: These shouldn't really be here, but C++ (alBuffer.cpp) won't turn
+ * these extern inline declarations into callable functions.
+ */
+extern inline void LockBufferList(ALCdevice *device);
+extern inline void UnlockBufferList(ALCdevice *device);
+extern inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
+extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
+
/* ALCcontext_DeferUpdates
*
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 03abb116..ee3ed68f 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -80,7 +80,7 @@ extern inline size_t clampz(size_t val, size_t min, size_t max);
extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu);
extern inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu);
-extern inline void aluVectorSet(aluVector *restrict vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w);
+extern inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w);
extern inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3);
@@ -90,6 +90,11 @@ extern inline void aluMatrixfSet(aluMatrixf *matrix,
ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33);
+extern inline void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
+extern inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
+extern inline float ScaleAzimuthFront(float azimuth, float scale);
+extern inline void ComputePanGains(const MixParams *dry, const ALfloat*RESTRICT coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+
/* Cone scalar */
ALfloat ConeScale = 1.0f;
@@ -1563,12 +1568,12 @@ static void ProcessParamUpdates(ALCcontext *ctx, const struct ALeffectslotArray
}
-static void ApplyStablizer(FrontStablizer *Stablizer, ALfloat (*restrict Buffer)[BUFFERSIZE],
+static void ApplyStablizer(FrontStablizer *Stablizer, ALfloat (*RESTRICT Buffer)[BUFFERSIZE],
int lidx, int ridx, int cidx, ALsizei SamplesToDo,
ALsizei NumChannels)
{
- ALfloat (*restrict lsplit)[BUFFERSIZE] = ASSUME_ALIGNED(Stablizer->LSplit, 16);
- ALfloat (*restrict rsplit)[BUFFERSIZE] = ASSUME_ALIGNED(Stablizer->RSplit, 16);
+ ALfloat (*RESTRICT lsplit)[BUFFERSIZE] = ASSUME_ALIGNED(Stablizer->LSplit, 16);
+ ALfloat (*RESTRICT rsplit)[BUFFERSIZE] = ASSUME_ALIGNED(Stablizer->RSplit, 16);
ALsizei i;
/* Apply an all-pass to all channels, except the front-left and front-
@@ -1611,18 +1616,18 @@ static void ApplyStablizer(FrontStablizer *Stablizer, ALfloat (*restrict Buffer)
}
}
-static void ApplyDistanceComp(ALfloat (*restrict Samples)[BUFFERSIZE], DistanceComp *distcomp,
- ALfloat *restrict Values, ALsizei SamplesToDo, ALsizei numchans)
+static void ApplyDistanceComp(ALfloat (*RESTRICT Samples)[BUFFERSIZE], DistanceComp *distcomp,
+ ALfloat *RESTRICT Values, ALsizei SamplesToDo, ALsizei numchans)
{
ALsizei i, c;
Values = ASSUME_ALIGNED(Values, 16);
for(c = 0;c < numchans;c++)
{
- ALfloat *restrict inout = ASSUME_ALIGNED(Samples[c], 16);
+ ALfloat *RESTRICT inout = ASSUME_ALIGNED(Samples[c], 16);
const ALfloat gain = distcomp[c].Gain;
const ALsizei base = distcomp[c].Length;
- ALfloat *restrict distbuf = ASSUME_ALIGNED(distcomp[c].Buffer, 16);
+ ALfloat *RESTRICT distbuf = ASSUME_ALIGNED(distcomp[c].Buffer, 16);
if(base == 0)
{
@@ -1654,7 +1659,7 @@ static void ApplyDistanceComp(ALfloat (*restrict Samples)[BUFFERSIZE], DistanceC
}
}
-static void ApplyDither(ALfloat (*restrict Samples)[BUFFERSIZE], ALuint *dither_seed,
+static void ApplyDither(ALfloat (*RESTRICT Samples)[BUFFERSIZE], ALuint *dither_seed,
const ALfloat quant_scale, const ALsizei SamplesToDo,
const ALsizei numchans)
{
@@ -1671,7 +1676,7 @@ static void ApplyDither(ALfloat (*restrict Samples)[BUFFERSIZE], ALuint *dither_
*/
for(c = 0;c < numchans;c++)
{
- ALfloat *restrict samples = Samples[c];
+ ALfloat *RESTRICT samples = Samples[c];
for(i = 0;i < SamplesToDo;i++)
{
ALfloat val = samples[i] * quant_scale;
@@ -1712,7 +1717,7 @@ DECL_TEMPLATE(ALuint, Conv_ALint, 2147483648u)
#undef DECL_TEMPLATE
#define DECL_TEMPLATE(T, A) \
-static void Write##A(const ALfloat (*restrict InBuffer)[BUFFERSIZE], \
+static void Write##A(const ALfloat (*RESTRICT InBuffer)[BUFFERSIZE], \
ALvoid *OutBuffer, ALsizei Offset, ALsizei SamplesToDo, \
ALsizei numchans) \
{ \
@@ -1723,8 +1728,8 @@ static void Write##A(const ALfloat (*restrict InBuffer)[BUFFERSIZE], \
\
for(j = 0;j < numchans;j++) \
{ \
- const ALfloat *restrict in = ASSUME_ALIGNED(InBuffer[j], 16); \
- T *restrict out = (T*)OutBuffer + Offset*numchans + j; \
+ const ALfloat *RESTRICT in = ASSUME_ALIGNED(InBuffer[j], 16); \
+ T *RESTRICT out = (T*)OutBuffer + Offset*numchans + j; \
\
for(i = 0;i < SamplesToDo;i++) \
out[i*numchans] = Conv_##T(in[i]); \
diff --git a/Alc/alconfig.c b/Alc/alconfig.c
index 3d0ed140..050391af 100644
--- a/Alc/alconfig.c
+++ b/Alc/alconfig.c
@@ -635,7 +635,7 @@ const char *GetConfigValue(const char *devName, const char *blockName, const cha
int ConfigValueExists(const char *devName, const char *blockName, const char *keyName)
{
const char *val = GetConfigValue(devName, blockName, keyName, "");
- return !!val[0];
+ return val[0] != 0;
}
int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret)
@@ -692,7 +692,7 @@ int GetConfigValueBool(const char *devName, const char *blockName, const char *k
{
const char *val = GetConfigValue(devName, blockName, keyName, "");
- if(!val[0]) return !!def;
+ if(!val[0]) return def != 0;
return (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 ||
strcasecmp(val, "on") == 0 || atoi(val) != 0);
}
diff --git a/Alc/alconfig.h b/Alc/alconfig.h
index 1e493e2e..cb8d8717 100644
--- a/Alc/alconfig.h
+++ b/Alc/alconfig.h
@@ -1,6 +1,10 @@
#ifndef ALCONFIG_H
#define ALCONFIG_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void ReadALConfig(void);
void FreeALConfig(void);
@@ -14,4 +18,8 @@ int ConfigValueUInt(const char *devName, const char *blockName, const char *keyN
int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret);
int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* ALCONFIG_H */
diff --git a/Alc/ambdec.c b/Alc/ambdec.c
deleted file mode 100644
index da114335..00000000
--- a/Alc/ambdec.c
+++ /dev/null
@@ -1,566 +0,0 @@
-
-#include "config.h"
-
-#include "ambdec.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "compat.h"
-
-
-static char *lstrip(char *line)
-{
- while(isspace(line[0]))
- line++;
- return line;
-}
-
-static char *rstrip(char *line)
-{
- size_t len = strlen(line);
- while(len > 0 && isspace(line[len-1]))
- len--;
- line[len] = 0;
- return line;
-}
-
-static int readline(FILE *f, char **output, size_t *maxlen)
-{
- size_t len = 0;
- int c;
-
- while((c=fgetc(f)) != EOF && (c == '\r' || c == '\n'))
- ;
- if(c == EOF)
- return 0;
-
- do {
- if(len+1 >= *maxlen)
- {
- void *temp = NULL;
- size_t newmax;
-
- newmax = (*maxlen ? (*maxlen)<<1 : 32);
- if(newmax > *maxlen)
- temp = realloc(*output, newmax);
- if(!temp)
- {
- ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, *maxlen);
- return 0;
- }
-
- *output = temp;
- *maxlen = newmax;
- }
- (*output)[len++] = c;
- (*output)[len] = '\0';
- } while((c=fgetc(f)) != EOF && c != '\r' && c != '\n');
-
- return 1;
-}
-
-
-/* Custom strtok_r, since we can't rely on it existing. */
-static char *my_strtok_r(char *str, const char *delim, char **saveptr)
-{
- /* Sanity check and update internal pointer. */
- if(!saveptr || !delim) return NULL;
- if(str) *saveptr = str;
- str = *saveptr;
-
- /* Nothing more to do with this string. */
- if(!str) return NULL;
-
- /* Find the first non-delimiter character. */
- while(*str != '\0' && strchr(delim, *str) != NULL)
- str++;
- if(*str == '\0')
- {
- /* End of string. */
- *saveptr = NULL;
- return NULL;
- }
-
- /* Find the next delimiter character. */
- *saveptr = strpbrk(str, delim);
- if(*saveptr) *((*saveptr)++) = '\0';
-
- return str;
-}
-
-static char *read_int(ALint *num, const char *line, int base)
-{
- char *end;
- *num = strtol(line, &end, base);
- if(end && *end != '\0')
- end = lstrip(end);
- return end;
-}
-
-static char *read_uint(ALuint *num, const char *line, int base)
-{
- char *end;
- *num = strtoul(line, &end, base);
- if(end && *end != '\0')
- end = lstrip(end);
- return end;
-}
-
-static char *read_float(ALfloat *num, const char *line)
-{
- char *end;
-#ifdef HAVE_STRTOF
- *num = strtof(line, &end);
-#else
- *num = (ALfloat)strtod(line, &end);
-#endif
- if(end && *end != '\0')
- end = lstrip(end);
- return end;
-}
-
-
-char *read_clipped_line(FILE *f, char **buffer, size_t *maxlen)
-{
- while(readline(f, buffer, maxlen))
- {
- char *line, *comment;
-
- line = lstrip(*buffer);
- comment = strchr(line, '#');
- if(comment) *(comment++) = 0;
-
- line = rstrip(line);
- if(line[0]) return line;
- }
- return NULL;
-}
-
-static int load_ambdec_speakers(AmbDecConf *conf, FILE *f, char **buffer, size_t *maxlen, char **saveptr)
-{
- ALsizei cur = 0;
- while(cur < conf->NumSpeakers)
- {
- const char *cmd = my_strtok_r(NULL, " \t", saveptr);
- if(!cmd)
- {
- char *line = read_clipped_line(f, buffer, maxlen);
- if(!line)
- {
- ERR("Unexpected end of file\n");
- return 0;
- }
- cmd = my_strtok_r(line, " \t", saveptr);
- }
-
- if(strcmp(cmd, "add_spkr") == 0)
- {
- const char *name = my_strtok_r(NULL, " \t", saveptr);
- const char *dist = my_strtok_r(NULL, " \t", saveptr);
- const char *az = my_strtok_r(NULL, " \t", saveptr);
- const char *elev = my_strtok_r(NULL, " \t", saveptr);
- const char *conn = my_strtok_r(NULL, " \t", saveptr);
-
- if(!name) WARN("Name not specified for speaker %u\n", cur+1);
- else alstr_copy_cstr(&conf->Speakers[cur].Name, name);
- if(!dist) WARN("Distance not specified for speaker %u\n", cur+1);
- else read_float(&conf->Speakers[cur].Distance, dist);
- if(!az) WARN("Azimuth not specified for speaker %u\n", cur+1);
- else read_float(&conf->Speakers[cur].Azimuth, az);
- if(!elev) WARN("Elevation not specified for speaker %u\n", cur+1);
- else read_float(&conf->Speakers[cur].Elevation, elev);
- if(!conn) TRACE("Connection not specified for speaker %u\n", cur+1);
- else alstr_copy_cstr(&conf->Speakers[cur].Connection, conn);
-
- cur++;
- }
- else
- {
- ERR("Unexpected speakers command: %s\n", cmd);
- return 0;
- }
-
- cmd = my_strtok_r(NULL, " \t", saveptr);
- if(cmd)
- {
- ERR("Unexpected junk on line: %s\n", cmd);
- return 0;
- }
- }
-
- return 1;
-}
-
-static int load_ambdec_matrix(ALfloat *gains, ALfloat (*matrix)[MAX_AMBI_COEFFS], ALsizei maxrow, FILE *f, char **buffer, size_t *maxlen, char **saveptr)
-{
- int gotgains = 0;
- ALsizei cur = 0;
- while(cur < maxrow)
- {
- const char *cmd = my_strtok_r(NULL, " \t", saveptr);
- if(!cmd)
- {
- char *line = read_clipped_line(f, buffer, maxlen);
- if(!line)
- {
- ERR("Unexpected end of file\n");
- return 0;
- }
- cmd = my_strtok_r(line, " \t", saveptr);
- }
-
- if(strcmp(cmd, "order_gain") == 0)
- {
- ALuint curgain = 0;
- char *line;
- while((line=my_strtok_r(NULL, " \t", saveptr)) != NULL)
- {
- ALfloat value;
- line = read_float(&value, line);
- if(line && *line != '\0')
- {
- ERR("Extra junk on gain %u: %s\n", curgain+1, line);
- return 0;
- }
- if(curgain < MAX_AMBI_ORDER+1)
- gains[curgain] = value;
- curgain++;
- }
- while(curgain < MAX_AMBI_ORDER+1)
- gains[curgain++] = 0.0f;
- gotgains = 1;
- }
- else if(strcmp(cmd, "add_row") == 0)
- {
- ALuint curidx = 0;
- char *line;
- while((line=my_strtok_r(NULL, " \t", saveptr)) != NULL)
- {
- ALfloat value;
- line = read_float(&value, line);
- if(line && *line != '\0')
- {
- ERR("Extra junk on matrix element %ux%u: %s\n", cur, curidx, line);
- return 0;
- }
- if(curidx < MAX_AMBI_COEFFS)
- matrix[cur][curidx] = value;
- curidx++;
- }
- while(curidx < MAX_AMBI_COEFFS)
- matrix[cur][curidx++] = 0.0f;
- cur++;
- }
- else
- {
- ERR("Unexpected speakers command: %s\n", cmd);
- return 0;
- }
-
- cmd = my_strtok_r(NULL, " \t", saveptr);
- if(cmd)
- {
- ERR("Unexpected junk on line: %s\n", cmd);
- return 0;
- }
- }
-
- if(!gotgains)
- {
- ERR("Matrix order_gain not specified\n");
- return 0;
- }
-
- return 1;
-}
-
-void ambdec_init(AmbDecConf *conf)
-{
- ALsizei i;
-
- memset(conf, 0, sizeof(*conf));
- AL_STRING_INIT(conf->Description);
- for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
- {
- AL_STRING_INIT(conf->Speakers[i].Name);
- AL_STRING_INIT(conf->Speakers[i].Connection);
- }
-}
-
-void ambdec_deinit(AmbDecConf *conf)
-{
- ALsizei i;
-
- alstr_reset(&conf->Description);
- for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
- {
- alstr_reset(&conf->Speakers[i].Name);
- alstr_reset(&conf->Speakers[i].Connection);
- }
- memset(conf, 0, sizeof(*conf));
-}
-
-int ambdec_load(AmbDecConf *conf, const char *fname)
-{
- char *buffer = NULL;
- size_t maxlen = 0;
- char *line;
- FILE *f;
-
- f = al_fopen(fname, "r");
- if(!f)
- {
- ERR("Failed to open: %s\n", fname);
- return 0;
- }
-
- while((line=read_clipped_line(f, &buffer, &maxlen)) != NULL)
- {
- char *saveptr;
- char *command;
-
- command = my_strtok_r(line, "/ \t", &saveptr);
- if(!command)
- {
- ERR("Malformed line: %s\n", line);
- goto fail;
- }
-
- if(strcmp(command, "description") == 0)
- {
- char *value = my_strtok_r(NULL, "", &saveptr);
- alstr_copy_cstr(&conf->Description, lstrip(value));
- }
- else if(strcmp(command, "version") == 0)
- {
- line = my_strtok_r(NULL, "", &saveptr);
- line = read_uint(&conf->Version, line, 10);
- if(line && *line != '\0')
- {
- ERR("Extra junk after version: %s\n", line);
- goto fail;
- }
- if(conf->Version != 3)
- {
- ERR("Unsupported version: %u\n", conf->Version);
- goto fail;
- }
- }
- else if(strcmp(command, "dec") == 0)
- {
- const char *dec = my_strtok_r(NULL, "/ \t", &saveptr);
- if(strcmp(dec, "chan_mask") == 0)
- {
- line = my_strtok_r(NULL, "", &saveptr);
- line = read_uint(&conf->ChanMask, line, 16);
- if(line && *line != '\0')
- {
- ERR("Extra junk after mask: %s\n", line);
- goto fail;
- }
- }
- else if(strcmp(dec, "freq_bands") == 0)
- {
- line = my_strtok_r(NULL, "", &saveptr);
- line = read_uint(&conf->FreqBands, line, 10);
- if(line && *line != '\0')
- {
- ERR("Extra junk after freq_bands: %s\n", line);
- goto fail;
- }
- if(conf->FreqBands != 1 && conf->FreqBands != 2)
- {
- ERR("Invalid freq_bands value: %u\n", conf->FreqBands);
- goto fail;
- }
- }
- else if(strcmp(dec, "speakers") == 0)
- {
- line = my_strtok_r(NULL, "", &saveptr);
- line = read_int(&conf->NumSpeakers, line, 10);
- if(line && *line != '\0')
- {
- ERR("Extra junk after speakers: %s\n", line);
- goto fail;
- }
- if(conf->NumSpeakers > MAX_OUTPUT_CHANNELS)
- {
- ERR("Unsupported speaker count: %u\n", conf->NumSpeakers);
- goto fail;
- }
- }
- else if(strcmp(dec, "coeff_scale") == 0)
- {
- line = my_strtok_r(NULL, " \t", &saveptr);
- if(strcmp(line, "n3d") == 0)
- conf->CoeffScale = ADS_N3D;
- else if(strcmp(line, "sn3d") == 0)
- conf->CoeffScale = ADS_SN3D;
- else if(strcmp(line, "fuma") == 0)
- conf->CoeffScale = ADS_FuMa;
- else
- {
- ERR("Unsupported coeff scale: %s\n", line);
- goto fail;
- }
- }
- else
- {
- ERR("Unexpected /dec option: %s\n", dec);
- goto fail;
- }
- }
- else if(strcmp(command, "opt") == 0)
- {
- const char *opt = my_strtok_r(NULL, "/ \t", &saveptr);
- if(strcmp(opt, "xover_freq") == 0)
- {
- line = my_strtok_r(NULL, "", &saveptr);
- line = read_float(&conf->XOverFreq, line);
- if(line && *line != '\0')
- {
- ERR("Extra junk after xover_freq: %s\n", line);
- goto fail;
- }
- }
- else if(strcmp(opt, "xover_ratio") == 0)
- {
- line = my_strtok_r(NULL, "", &saveptr);
- line = read_float(&conf->XOverRatio, line);
- if(line && *line != '\0')
- {
- ERR("Extra junk after xover_ratio: %s\n", line);
- goto fail;
- }
- }
- else if(strcmp(opt, "input_scale") == 0 || strcmp(opt, "nfeff_comp") == 0 ||
- strcmp(opt, "delay_comp") == 0 || strcmp(opt, "level_comp") == 0)
- {
- /* Unused */
- my_strtok_r(NULL, " \t", &saveptr);
- }
- else
- {
- ERR("Unexpected /opt option: %s\n", opt);
- goto fail;
- }
- }
- else if(strcmp(command, "speakers") == 0)
- {
- const char *value = my_strtok_r(NULL, "/ \t", &saveptr);
- if(strcmp(value, "{") != 0)
- {
- ERR("Expected { after %s command, got %s\n", command, value);
- goto fail;
- }
- if(!load_ambdec_speakers(conf, f, &buffer, &maxlen, &saveptr))
- goto fail;
- value = my_strtok_r(NULL, "/ \t", &saveptr);
- if(!value)
- {
- line = read_clipped_line(f, &buffer, &maxlen);
- if(!line)
- {
- ERR("Unexpected end of file\n");
- goto fail;
- }
- value = my_strtok_r(line, "/ \t", &saveptr);
- }
- if(strcmp(value, "}") != 0)
- {
- ERR("Expected } after speaker definitions, got %s\n", value);
- goto fail;
- }
- }
- else if(strcmp(command, "lfmatrix") == 0 || strcmp(command, "hfmatrix") == 0 ||
- strcmp(command, "matrix") == 0)
- {
- const char *value = my_strtok_r(NULL, "/ \t", &saveptr);
- if(strcmp(value, "{") != 0)
- {
- ERR("Expected { after %s command, got %s\n", command, value);
- goto fail;
- }
- if(conf->FreqBands == 1)
- {
- if(strcmp(command, "matrix") != 0)
- {
- ERR("Unexpected \"%s\" type for a single-band decoder\n", command);
- goto fail;
- }
- if(!load_ambdec_matrix(conf->HFOrderGain, conf->HFMatrix, conf->NumSpeakers,
- f, &buffer, &maxlen, &saveptr))
- goto fail;
- }
- else
- {
- if(strcmp(command, "lfmatrix") == 0)
- {
- if(!load_ambdec_matrix(conf->LFOrderGain, conf->LFMatrix, conf->NumSpeakers,
- f, &buffer, &maxlen, &saveptr))
- goto fail;
- }
- else if(strcmp(command, "hfmatrix") == 0)
- {
- if(!load_ambdec_matrix(conf->HFOrderGain, conf->HFMatrix, conf->NumSpeakers,
- f, &buffer, &maxlen, &saveptr))
- goto fail;
- }
- else
- {
- ERR("Unexpected \"%s\" type for a dual-band decoder\n", command);
- goto fail;
- }
- }
- value = my_strtok_r(NULL, "/ \t", &saveptr);
- if(!value)
- {
- line = read_clipped_line(f, &buffer, &maxlen);
- if(!line)
- {
- ERR("Unexpected end of file\n");
- goto fail;
- }
- value = my_strtok_r(line, "/ \t", &saveptr);
- }
- if(strcmp(value, "}") != 0)
- {
- ERR("Expected } after matrix definitions, got %s\n", value);
- goto fail;
- }
- }
- else if(strcmp(command, "end") == 0)
- {
- line = my_strtok_r(NULL, "/ \t", &saveptr);
- if(line)
- {
- ERR("Unexpected junk on end: %s\n", line);
- goto fail;
- }
-
- fclose(f);
- free(buffer);
- return 1;
- }
- else
- {
- ERR("Unexpected command: %s\n", command);
- goto fail;
- }
-
- line = my_strtok_r(NULL, "/ \t", &saveptr);
- if(line)
- {
- ERR("Unexpected junk on line: %s\n", line);
- goto fail;
- }
- }
- ERR("Unexpected end of file\n");
-
-fail:
- fclose(f);
- free(buffer);
- return 0;
-}
diff --git a/Alc/ambdec.cpp b/Alc/ambdec.cpp
new file mode 100644
index 00000000..088d4a85
--- /dev/null
+++ b/Alc/ambdec.cpp
@@ -0,0 +1,425 @@
+
+#include "config.h"
+
+#include "ambdec.h"
+
+#include <cstring>
+#include <cctype>
+
+#include <limits>
+#include <string>
+#include <fstream>
+#include <sstream>
+
+#include "compat.h"
+
+
+namespace {
+
+int readline(std::istream &f, std::string &output)
+{
+ while(f.good() && f.peek() == '\n')
+ f.ignore();
+
+ std::getline(f, output);
+ return !output.empty();
+}
+
+bool read_clipped_line(std::istream &f, std::string &buffer)
+{
+ while(readline(f, buffer))
+ {
+ std::size_t pos{0};
+ while(pos < buffer.length() && std::isspace(buffer[pos]))
+ pos++;
+ buffer.erase(0, pos);
+
+ std::size_t cmtpos{buffer.find_first_of('#')};
+ if(cmtpos < buffer.length())
+ buffer.resize(cmtpos);
+ while(!buffer.empty() && std::isspace(buffer.back()))
+ buffer.pop_back();
+
+ if(!buffer.empty())
+ return true;
+ }
+ return false;
+}
+
+
+std::string read_word(std::istream &f)
+{
+ std::string ret;
+ f >> ret;
+ return ret;
+}
+
+bool is_at_end(const std::string &buffer, std::size_t endpos)
+{
+ while(endpos < buffer.length() && std::isspace(buffer[endpos]))
+ ++endpos;
+ if(endpos < buffer.length())
+ return false;
+ return true;
+}
+
+
+bool load_ambdec_speakers(AmbDecConf *conf, std::istream &f, std::string &buffer)
+{
+ ALsizei cur = 0;
+ while(cur < conf->NumSpeakers)
+ {
+ std::istringstream istr{buffer};
+
+ std::string cmd{read_word(istr)};
+ if(cmd.empty())
+ {
+ if(!read_clipped_line(f, buffer))
+ {
+ ERR("Unexpected end of file\n");
+ return false;
+ }
+ continue;
+ }
+
+ if(cmd == "add_spkr")
+ {
+ istr >> conf->Speakers[cur].Name;
+ if(istr.fail()) WARN("Name not specified for speaker %u\n", cur+1);
+ istr >> conf->Speakers[cur].Distance;
+ if(istr.fail()) WARN("Distance not specified for speaker %u\n", cur+1);
+ istr >> conf->Speakers[cur].Azimuth;
+ if(istr.fail()) WARN("Azimuth not specified for speaker %u\n", cur+1);
+ istr >> conf->Speakers[cur].Elevation;
+ if(istr.fail()) WARN("Elevation not specified for speaker %u\n", cur+1);
+ istr >> conf->Speakers[cur].Connection;
+ if(istr.fail()) TRACE("Connection not specified for speaker %u\n", cur+1);
+
+ cur++;
+ }
+ else
+ {
+ ERR("Unexpected speakers command: %s\n", cmd.c_str());
+ return false;
+ }
+
+ istr.clear();
+ std::istream::pos_type endpos{istr.tellg()};
+ if(!is_at_end(buffer, endpos))
+ {
+ ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
+ return false;
+ }
+ buffer.clear();
+ }
+
+ return true;
+}
+
+bool load_ambdec_matrix(ALfloat *gains, ALfloat (*matrix)[MAX_AMBI_COEFFS], ALsizei maxrow, std::istream &f, std::string &buffer)
+{
+ bool gotgains = false;
+ ALsizei cur = 0;
+ while(cur < maxrow)
+ {
+ std::istringstream istr{buffer};
+
+ std::string cmd{read_word(istr)};
+ if(cmd.empty())
+ {
+ if(!read_clipped_line(f, buffer))
+ {
+ ERR("Unexpected end of file\n");
+ return false;
+ }
+ continue;
+ }
+
+ if(cmd == "order_gain")
+ {
+ ALuint curgain = 0;
+ float value;
+ while(istr.good())
+ {
+ istr >> value;
+ if(istr.fail()) break;
+ if(!istr.eof() && !std::isspace(istr.peek()))
+ {
+ ERR("Extra junk on gain %u: %s\n", curgain+1, buffer.c_str()+istr.tellg());
+ return false;
+ }
+ if(curgain < MAX_AMBI_ORDER+1)
+ gains[curgain++] = value;
+ }
+ while(curgain < MAX_AMBI_ORDER+1)
+ gains[curgain++] = 0.0f;
+ gotgains = true;
+ }
+ else if(cmd == "add_row")
+ {
+ ALuint curidx = 0;
+ float value;
+ while(istr.good())
+ {
+ istr >> value;
+ if(istr.fail()) break;
+ if(!istr.eof() && !std::isspace(istr.peek()))
+ {
+ ERR("Extra junk on matrix element %ux%u: %s\n", cur, curidx,
+ buffer.c_str()+istr.tellg());
+ return false;
+ }
+ if(curidx < MAX_AMBI_COEFFS)
+ matrix[cur][curidx++] = value;
+ }
+ while(curidx < MAX_AMBI_COEFFS)
+ matrix[cur][curidx++] = 0.0f;
+ cur++;
+ }
+ else
+ {
+ ERR("Unexpected matrix command: %s\n", cmd.c_str());
+ return false;
+ }
+
+ istr.clear();
+ std::istream::pos_type endpos{istr.tellg()};
+ if(!is_at_end(buffer, endpos))
+ {
+ ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
+ return false;
+ }
+ buffer.clear();
+ }
+
+ if(!gotgains)
+ {
+ ERR("Matrix order_gain not specified\n");
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
+int AmbDecConf::load(const char *fname)
+{
+ al::ifstream f{fname};
+ if(!f.is_open())
+ {
+ ERR("Failed to open: %s\n", fname);
+ return 0;
+ }
+
+ std::string buffer;
+ while(read_clipped_line(f, buffer))
+ {
+ std::istringstream istr{buffer};
+
+ std::string command{read_word(istr)};
+ if(command.empty())
+ {
+ ERR("Malformed line: %s\n", buffer.c_str());
+ return 0;
+ }
+
+ if(command == "/description")
+ istr >> Description;
+ else if(command == "/version")
+ {
+ istr >> Version;
+ if(!istr.eof() && !std::isspace(istr.peek()))
+ {
+ ERR("Extra junk after version: %s\n", buffer.c_str()+istr.tellg());
+ return 0;
+ }
+ if(Version != 3)
+ {
+ ERR("Unsupported version: %u\n", Version);
+ return 0;
+ }
+ }
+ else if(command == "/dec/chan_mask")
+ {
+ istr >> std::hex >> ChanMask >> std::dec;
+ if(!istr.eof() && !std::isspace(istr.peek()))
+ {
+ ERR("Extra junk after mask: %s\n", buffer.c_str()+istr.tellg());
+ return 0;
+ }
+ }
+ else if(command == "/dec/freq_bands")
+ {
+ istr >> FreqBands;
+ if(!istr.eof() && !std::isspace(istr.peek()))
+ {
+ ERR("Extra junk after freq_bands: %s\n", buffer.c_str()+istr.tellg());
+ return 0;
+ }
+ if(FreqBands != 1 && FreqBands != 2)
+ {
+ ERR("Invalid freq_bands value: %u\n", FreqBands);
+ return 0;
+ }
+ }
+ else if(command == "/dec/speakers")
+ {
+ istr >> NumSpeakers;
+ if(!istr.eof() && !std::isspace(istr.peek()))
+ {
+ ERR("Extra junk after speakers: %s\n", buffer.c_str()+istr.tellg());
+ return 0;
+ }
+ if(NumSpeakers > MAX_OUTPUT_CHANNELS)
+ {
+ ERR("Unsupported speaker count: %u\n", NumSpeakers);
+ return 0;
+ }
+ }
+ else if(command == "/dec/coeff_scale")
+ {
+ std::string scale = read_word(istr);
+ if(scale == "n3d") CoeffScale = AmbDecScale::N3D;
+ else if(scale == "sn3d") CoeffScale = AmbDecScale::SN3D;
+ else if(scale == "fuma") CoeffScale = AmbDecScale::FuMa;
+ else
+ {
+ ERR("Unsupported coeff scale: %s\n", scale.c_str());
+ return 0;
+ }
+ }
+ else if(command == "/opt/xover_freq")
+ {
+ istr >> XOverFreq;
+ if(!istr.eof() && !std::isspace(istr.peek()))
+ {
+ ERR("Extra junk after xover_freq: %s\n", buffer.c_str()+istr.tellg());
+ return 0;
+ }
+ }
+ else if(command == "/opt/xover_ratio")
+ {
+ istr >> XOverRatio;
+ if(!istr.eof() && !std::isspace(istr.peek()))
+ {
+ ERR("Extra junk after xover_ratio: %s\n", buffer.c_str()+istr.tellg());
+ return 0;
+ }
+ }
+ else if(command == "/opt/input_scale" || command == "/opt/nfeff_comp" ||
+ command == "/opt/delay_comp" || command == "/opt/level_comp")
+ {
+ /* Unused */
+ read_word(istr);
+ }
+ else if(command == "/speakers/{")
+ {
+ std::istream::pos_type endpos{istr.tellg()};
+ if(!is_at_end(buffer, endpos))
+ {
+ ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
+ return 0;
+ }
+ buffer.clear();
+
+ if(!load_ambdec_speakers(this, f, buffer))
+ return 0;
+
+ if(!read_clipped_line(f, buffer))
+ {
+ ERR("Unexpected end of file\n");
+ return 0;
+ }
+ std::istringstream istr2{buffer};
+ std::string endmark{read_word(istr2)};
+ if(endmark != "/}")
+ {
+ ERR("Expected /} after speaker definitions, got %s\n", endmark.c_str());
+ return 0;
+ }
+ istr.swap(istr2);
+ }
+ else if(command == "/lfmatrix/{" || command == "/hfmatrix/{" || command == "/matrix/{")
+ {
+ std::istream::pos_type endpos{istr.tellg()};
+ if(!is_at_end(buffer, endpos))
+ {
+ ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
+ return 0;
+ }
+ buffer.clear();
+
+ if(FreqBands == 1)
+ {
+ if(command != "/matrix/{")
+ {
+ ERR("Unexpected \"%s\" type for a single-band decoder\n", command.c_str());
+ return 0;
+ }
+ if(!load_ambdec_matrix(HFOrderGain, HFMatrix, NumSpeakers, f, buffer))
+ return 0;
+ }
+ else
+ {
+ if(command == "/lfmatrix/{")
+ {
+ if(!load_ambdec_matrix(LFOrderGain, LFMatrix, NumSpeakers, f, buffer))
+ return 0;
+ }
+ else if(command == "/hfmatrix/{")
+ {
+ if(!load_ambdec_matrix(HFOrderGain, HFMatrix, NumSpeakers, f, buffer))
+ return 0;
+ }
+ else
+ {
+ ERR("Unexpected \"%s\" type for a dual-band decoder\n", command.c_str());
+ return 0;
+ }
+ }
+
+ if(!read_clipped_line(f, buffer))
+ {
+ ERR("Unexpected end of file\n");
+ return 0;
+ }
+ std::istringstream istr2{buffer};
+ std::string endmark{read_word(istr2)};
+ if(endmark != "/}")
+ {
+ ERR("Expected /} after matrix definitions, got %s\n", endmark.c_str());
+ return 0;
+ }
+ istr.swap(istr2);
+ }
+ else if(command == "/end")
+ {
+ std::istream::pos_type endpos{istr.tellg()};
+ if(!is_at_end(buffer, endpos))
+ {
+ ERR("Unexpected junk on end: %s\n", buffer.c_str()+endpos);
+ return 0;
+ }
+
+ return 1;
+ }
+ else
+ {
+ ERR("Unexpected command: %s\n", command.c_str());
+ return 0;
+ }
+
+ istr.clear();
+ std::istream::pos_type endpos{istr.tellg()};
+ if(!is_at_end(buffer, endpos))
+ {
+ ERR("Unexpected junk on line: %s\n", buffer.c_str()+endpos);
+ return 0;
+ }
+ buffer.clear();
+ }
+ ERR("Unexpected end of file\n");
+
+ return 0;
+}
diff --git a/Alc/ambdec.h b/Alc/ambdec.h
index 0bb84072..d6d154fb 100644
--- a/Alc/ambdec.h
+++ b/Alc/ambdec.h
@@ -1,34 +1,35 @@
#ifndef AMBDEC_H
#define AMBDEC_H
-#include "alstring.h"
+#include <string>
+
#include "alMain.h"
/* Helpers to read .ambdec configuration files. */
-enum AmbDecScaleType {
- ADS_N3D,
- ADS_SN3D,
- ADS_FuMa,
+enum class AmbDecScale {
+ N3D,
+ SN3D,
+ FuMa,
};
-typedef struct AmbDecConf {
- al_string Description;
+struct AmbDecConf {
+ std::string Description;
ALuint Version; /* Must be 3 */
ALuint ChanMask;
ALuint FreqBands; /* Must be 1 or 2 */
ALsizei NumSpeakers;
- enum AmbDecScaleType CoeffScale;
+ AmbDecScale CoeffScale;
ALfloat XOverFreq;
ALfloat XOverRatio;
struct {
- al_string Name;
+ std::string Name;
ALfloat Distance;
ALfloat Azimuth;
ALfloat Elevation;
- al_string Connection;
+ std::string Connection;
} Speakers[MAX_OUTPUT_CHANNELS];
/* Unused when FreqBands == 1 */
@@ -37,10 +38,8 @@ typedef struct AmbDecConf {
ALfloat HFOrderGain[MAX_AMBI_ORDER+1];
ALfloat HFMatrix[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
-} AmbDecConf;
-void ambdec_init(AmbDecConf *conf);
-void ambdec_deinit(AmbDecConf *conf);
-int ambdec_load(AmbDecConf *conf, const char *fname);
+ int load(const char *fname);
+};
#endif /* AMBDEC_H */
diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c
index a967fff0..6f22ae60 100644
--- a/Alc/backends/alsa.c
+++ b/Alc/backends/alsa.c
@@ -119,6 +119,7 @@ static void *alsa_handle;
ALSA_FUNCS(MAKE_FUNC);
#undef MAKE_FUNC
+#ifndef IN_IDE_PARSER
#define snd_strerror psnd_strerror
#define snd_pcm_open psnd_pcm_open
#define snd_pcm_close psnd_pcm_close
@@ -192,6 +193,7 @@ ALSA_FUNCS(MAKE_FUNC);
#define snd_card_next psnd_card_next
#define snd_config_update_free_global psnd_config_update_free_global
#endif
+#endif
static ALCboolean alsa_load(void)
diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.cpp
index c368cffb..e760e9f5 100644
--- a/Alc/backends/dsound.c
+++ b/Alc/backends/dsound.cpp
@@ -32,12 +32,16 @@
#include <ksmedia.h>
#endif
+#include <atomic>
+#include <thread>
+#include <string>
+#include <vector>
+#include <algorithm>
+
#include "alMain.h"
#include "alu.h"
#include "ringbuffer.h"
-#include "threads.h"
#include "compat.h"
-#include "alstring.h"
#include "backends/base.h"
@@ -58,8 +62,18 @@
#endif
+/* Some headers seem to define these as macros for __uuidof, which is annoying
+ * since some headers don't declare them at all. Hopefully the ifdef is enough
+ * to tell if they need to be declared.
+ */
+#ifndef KSDATAFORMAT_SUBTYPE_PCM
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+#endif
+#ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+#endif
+
+namespace {
#define DEVNAME_HEAD "OpenAL Soft on "
@@ -71,11 +85,13 @@ static HRESULT (WINAPI *pDirectSoundEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallbac
static HRESULT (WINAPI *pDirectSoundCaptureCreate)(const GUID *pcGuidDevice, IDirectSoundCapture **ppDSC, IUnknown *pUnkOuter);
static HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext);
+#ifndef IN_IDE_PARSER
#define DirectSoundCreate pDirectSoundCreate
#define DirectSoundEnumerateW pDirectSoundEnumerateW
#define DirectSoundCaptureCreate pDirectSoundCaptureCreate
#define DirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW
#endif
+#endif
static ALCboolean DSoundLoad(void)
@@ -84,17 +100,18 @@ static ALCboolean DSoundLoad(void)
if(!ds_handle)
{
ds_handle = LoadLib("dsound.dll");
- if(ds_handle == NULL)
+ if(!ds_handle)
{
ERR("Failed to load dsound.dll\n");
return ALC_FALSE;
}
#define LOAD_FUNC(f) do { \
- p##f = GetSymbol(ds_handle, #f); \
- if(p##f == NULL) { \
+ p##f = reinterpret_cast<decltype(p##f)>(GetSymbol(ds_handle, #f)); \
+ if(!p##f) \
+ { \
CloseLib(ds_handle); \
- ds_handle = NULL; \
+ ds_handle = nullptr; \
return ALC_FALSE; \
} \
} while(0)
@@ -111,85 +128,72 @@ static ALCboolean DSoundLoad(void)
#define MAX_UPDATES 128
-typedef struct {
- al_string name;
+struct DevMap {
+ std::string name;
GUID guid;
-} DevMap;
-TYPEDEF_VECTOR(DevMap, vector_DevMap)
-static vector_DevMap PlaybackDevices;
-static vector_DevMap CaptureDevices;
+ template<typename T0, typename T1>
+ DevMap(T0&& name_, T1&& guid_)
+ : name{std::forward<T0>(name_)}, guid{std::forward<T1>(guid_)}
+ { }
+};
-static void clear_devlist(vector_DevMap *list)
+std::vector<DevMap> PlaybackDevices;
+std::vector<DevMap> CaptureDevices;
+
+bool checkName(const std::vector<DevMap> &list, const std::string &name)
{
-#define DEINIT_STR(i) AL_STRING_DEINIT((i)->name)
- VECTOR_FOR_EACH(DevMap, *list, DEINIT_STR);
- VECTOR_RESIZE(*list, 0, 0);
-#undef DEINIT_STR
+ return std::find_if(list.cbegin(), list.cend(),
+ [&name](const DevMap &entry) -> bool
+ { return entry.name == name; }
+ ) != list.cend();
}
-static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data)
+BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data)
{
- vector_DevMap *devices = data;
- OLECHAR *guidstr = NULL;
- DevMap entry;
- HRESULT hr;
- int count;
-
if(!guid)
return TRUE;
- AL_STRING_INIT(entry.name);
+ auto& devices = *reinterpret_cast<std::vector<DevMap>*>(data);
+ const std::string basename{DEVNAME_HEAD + wstr_to_utf8(desc)};
- count = 0;
- while(1)
+ int count{1};
+ std::string newname{basename};
+ while(checkName(devices, newname))
{
- const DevMap *iter;
-
- alstr_copy_cstr(&entry.name, DEVNAME_HEAD);
- alstr_append_wcstr(&entry.name, desc);
- if(count != 0)
- {
- char str[64];
- snprintf(str, sizeof(str), " #%d", count+1);
- alstr_append_cstr(&entry.name, str);
- }
-
-#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, *devices, MATCH_ENTRY);
- if(iter == VECTOR_END(*devices)) break;
-#undef MATCH_ENTRY
- count++;
+ newname = basename;
+ newname += " #";
+ newname += std::to_string(++count);
}
- entry.guid = *guid;
+ devices.emplace_back(std::move(newname), *guid);
+ const DevMap &newentry = devices.back();
- hr = StringFromCLSID(guid, &guidstr);
+ OLECHAR *guidstr{nullptr};
+ HRESULT hr{StringFromCLSID(*guid, &guidstr)};
if(SUCCEEDED(hr))
{
- TRACE("Got device \"%s\", GUID \"%ls\"\n", alstr_get_cstr(entry.name), guidstr);
+ TRACE("Got device \"%s\", GUID \"%ls\"\n", newentry.name.c_str(), guidstr);
CoTaskMemFree(guidstr);
}
- VECTOR_PUSH_BACK(*devices, entry);
-
return TRUE;
}
+} // namespace
-typedef struct ALCdsoundPlayback {
- DERIVE_FROM_TYPE(ALCbackend);
- IDirectSound *DS;
- IDirectSoundBuffer *PrimaryBuffer;
- IDirectSoundBuffer *Buffer;
- IDirectSoundNotify *Notifies;
- HANDLE NotifyEvent;
+struct ALCdsoundPlayback final : public ALCbackend {
+ IDirectSound *DS{nullptr};
+ IDirectSoundBuffer *PrimaryBuffer{nullptr};
+ IDirectSoundBuffer *Buffer{nullptr};
+ IDirectSoundNotify *Notifies{nullptr};
+ HANDLE NotifyEvent{nullptr};
- ATOMIC(ALenum) killNow;
- althrd_t thread;
-} ALCdsoundPlayback;
+ std::atomic<ALenum> killNow{AL_TRUE};
+ std::thread thread;
+};
-static int ALCdsoundPlayback_mixerProc(void *ptr);
+static int ALCdsoundPlayback_mixerProc(ALCdsoundPlayback *self);
static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device);
static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self);
@@ -209,61 +213,47 @@ DEFINE_ALCBACKEND_VTABLE(ALCdsoundPlayback);
static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device)
{
+ new (self) ALCdsoundPlayback{};
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
SET_VTABLE2(ALCdsoundPlayback, ALCbackend, self);
-
- self->DS = NULL;
- self->PrimaryBuffer = NULL;
- self->Buffer = NULL;
- self->Notifies = NULL;
- self->NotifyEvent = NULL;
- ATOMIC_INIT(&self->killNow, AL_TRUE);
}
static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self)
{
if(self->Notifies)
- IDirectSoundNotify_Release(self->Notifies);
- self->Notifies = NULL;
+ self->Notifies->Release();
+ self->Notifies = nullptr;
if(self->Buffer)
- IDirectSoundBuffer_Release(self->Buffer);
- self->Buffer = NULL;
- if(self->PrimaryBuffer != NULL)
- IDirectSoundBuffer_Release(self->PrimaryBuffer);
- self->PrimaryBuffer = NULL;
+ self->Buffer->Release();
+ self->Buffer = nullptr;
+ if(self->PrimaryBuffer)
+ self->PrimaryBuffer->Release();
+ self->PrimaryBuffer = nullptr;
if(self->DS)
- IDirectSound_Release(self->DS);
- self->DS = NULL;
+ self->DS->Release();
+ self->DS = nullptr;
if(self->NotifyEvent)
CloseHandle(self->NotifyEvent);
- self->NotifyEvent = NULL;
+ self->NotifyEvent = nullptr;
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+ self->~ALCdsoundPlayback();
}
-FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
+FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(ALCdsoundPlayback *self)
{
- ALCdsoundPlayback *self = ptr;
ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- DSBCAPS DSBCaps;
- DWORD LastCursor = 0;
- DWORD PlayCursor;
- void *WritePtr1, *WritePtr2;
- DWORD WriteCnt1, WriteCnt2;
- BOOL Playing = FALSE;
- DWORD FrameSize;
- DWORD FragSize;
- DWORD avail;
- HRESULT err;
SetRTPriority();
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
- memset(&DSBCaps, 0, sizeof(DSBCaps));
+ IDirectSoundBuffer *const Buffer{self->Buffer};
+
+ DSBCAPS DSBCaps{};
DSBCaps.dwSize = sizeof(DSBCaps);
- err = IDirectSoundBuffer_GetCaps(self->Buffer, &DSBCaps);
+ HRESULT err{Buffer->GetCaps(&DSBCaps)};
if(FAILED(err))
{
ERR("Failed to get buffer caps: 0x%lx\n", err);
@@ -273,22 +263,25 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
return 1;
}
- FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
- FragSize = device->UpdateSize * FrameSize;
+ ALsizei FrameSize{FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)};
+ DWORD FragSize{device->UpdateSize * FrameSize};
- IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL);
- while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+ bool Playing{false};
+ DWORD LastCursor{0u};
+ Buffer->GetCurrentPosition(&LastCursor, nullptr);
+ while(!self->killNow.load(std::memory_order_acquire) &&
ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
{
// Get current play cursor
- IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &PlayCursor, NULL);
- avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;
+ DWORD PlayCursor;
+ Buffer->GetCurrentPosition(&PlayCursor, nullptr);
+ DWORD avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;
if(avail < FragSize)
{
if(!Playing)
{
- err = IDirectSoundBuffer_Play(self->Buffer, 0, 0, DSBPLAY_LOOPING);
+ err = Buffer->Play(0, 0, DSBPLAY_LOOPING);
if(FAILED(err))
{
ERR("Failed to play buffer: 0x%lx\n", err);
@@ -297,7 +290,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
ALCdevice_Unlock(device);
return 1;
}
- Playing = TRUE;
+ Playing = true;
}
avail = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE);
@@ -308,20 +301,21 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
avail -= avail%FragSize;
// Lock output buffer
- WriteCnt1 = 0;
- WriteCnt2 = 0;
- err = IDirectSoundBuffer_Lock(self->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
+ void *WritePtr1, *WritePtr2;
+ DWORD WriteCnt1{0u}, WriteCnt2{0u};
+ err = Buffer->Lock(LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
// If the buffer is lost, restore it and lock
if(err == DSERR_BUFFERLOST)
{
WARN("Buffer lost, restoring...\n");
- err = IDirectSoundBuffer_Restore(self->Buffer);
+ err = Buffer->Restore();
if(SUCCEEDED(err))
{
- Playing = FALSE;
+ Playing = false;
LastCursor = 0;
- err = IDirectSoundBuffer_Lock(self->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
+ err = Buffer->Lock(0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1,
+ &WritePtr2, &WriteCnt2, 0);
}
}
@@ -335,7 +329,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
ALCdevice_Unlock(device);
// Unlock output buffer only when successfully locked
- IDirectSoundBuffer_Unlock(self->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
+ Buffer->Unlock(WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
}
else
{
@@ -356,14 +350,13 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *deviceName)
{
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- const GUID *guid = NULL;
- HRESULT hr, hrcom;
+ ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice};
- if(VECTOR_SIZE(PlaybackDevices) == 0)
+ HRESULT hr;
+ if(PlaybackDevices.empty())
{
/* Initialize COM to prevent name truncation */
- hrcom = CoInitialize(NULL);
+ HRESULT hrcom{CoInitialize(nullptr)};
hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices);
if(FAILED(hr))
ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr);
@@ -371,42 +364,34 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de
CoUninitialize();
}
- if(!deviceName && VECTOR_SIZE(PlaybackDevices) > 0)
+ const GUID *guid{nullptr};
+ if(!deviceName && !PlaybackDevices.empty())
{
- deviceName = alstr_get_cstr(VECTOR_FRONT(PlaybackDevices).name);
- guid = &VECTOR_FRONT(PlaybackDevices).guid;
+ deviceName = PlaybackDevices[0].name.c_str();
+ guid = &PlaybackDevices[0].guid;
}
else
{
- const DevMap *iter;
-
-#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0)
- VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
-#undef MATCH_NAME
- if(iter == VECTOR_END(PlaybackDevices))
+ auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
+ [deviceName](const DevMap &entry) -> bool
+ { return entry.name == deviceName; }
+ );
+ if(iter == PlaybackDevices.cend())
return ALC_INVALID_VALUE;
guid = &iter->guid;
}
hr = DS_OK;
- self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- if(self->NotifyEvent == NULL)
- hr = E_FAIL;
+ self->NotifyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
+ if(!self->NotifyEvent) hr = E_FAIL;
//DirectSound Init code
if(SUCCEEDED(hr))
- hr = DirectSoundCreate(guid, &self->DS, NULL);
+ hr = DirectSoundCreate(guid, &self->DS, nullptr);
if(SUCCEEDED(hr))
- hr = IDirectSound_SetCooperativeLevel(self->DS, GetForegroundWindow(), DSSCL_PRIORITY);
+ hr = self->DS->SetCooperativeLevel(GetForegroundWindow(), DSSCL_PRIORITY);
if(FAILED(hr))
{
- if(self->DS)
- IDirectSound_Release(self->DS);
- self->DS = NULL;
- if(self->NotifyEvent)
- CloseHandle(self->NotifyEvent);
- self->NotifyEvent = NULL;
-
ERR("Device init failed: 0x%08lx\n", hr);
return ALC_INVALID_VALUE;
}
@@ -419,22 +404,16 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de
static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
{
ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- DSBUFFERDESC DSBDescription;
- WAVEFORMATEXTENSIBLE OutputType;
- DWORD speakers;
- HRESULT hr;
-
- memset(&OutputType, 0, sizeof(OutputType));
if(self->Notifies)
- IDirectSoundNotify_Release(self->Notifies);
- self->Notifies = NULL;
+ self->Notifies->Release();
+ self->Notifies = nullptr;
if(self->Buffer)
- IDirectSoundBuffer_Release(self->Buffer);
- self->Buffer = NULL;
- if(self->PrimaryBuffer != NULL)
- IDirectSoundBuffer_Release(self->PrimaryBuffer);
- self->PrimaryBuffer = NULL;
+ self->Buffer->Release();
+ self->Buffer = nullptr;
+ if(self->PrimaryBuffer)
+ self->PrimaryBuffer->Release();
+ self->PrimaryBuffer = nullptr;
switch(device->FmtType)
{
@@ -457,7 +436,9 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
break;
}
- hr = IDirectSound_GetSpeakerConfig(self->DS, &speakers);
+ WAVEFORMATEXTENSIBLE OutputType{};
+ DWORD speakers;
+ HRESULT hr{self->DS->GetSpeakerConfig(&speakers)};
if(SUCCEEDED(hr))
{
speakers = DSSPEAKER_CONFIG(speakers);
@@ -558,20 +539,20 @@ retry_open:
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
if(self->PrimaryBuffer)
- IDirectSoundBuffer_Release(self->PrimaryBuffer);
- self->PrimaryBuffer = NULL;
+ self->PrimaryBuffer->Release();
+ self->PrimaryBuffer = nullptr;
}
else
{
if(SUCCEEDED(hr) && !self->PrimaryBuffer)
{
- memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
- DSBDescription.dwSize=sizeof(DSBUFFERDESC);
- DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER;
- hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->PrimaryBuffer, NULL);
+ DSBUFFERDESC DSBDescription{};
+ DSBDescription.dwSize = sizeof(DSBDescription);
+ DSBDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
+ hr = self->DS->CreateSoundBuffer(&DSBDescription, &self->PrimaryBuffer, nullptr);
}
if(SUCCEEDED(hr))
- hr = IDirectSoundBuffer_SetFormat(self->PrimaryBuffer,&OutputType.Format);
+ hr = self->PrimaryBuffer->SetFormat(&OutputType.Format);
}
if(SUCCEEDED(hr))
@@ -583,13 +564,15 @@ retry_open:
device->NumUpdates = MAX_UPDATES;
}
- memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
- DSBDescription.dwSize=sizeof(DSBUFFERDESC);
- DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS;
- DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates *
- OutputType.Format.nBlockAlign;
- DSBDescription.lpwfxFormat=&OutputType.Format;
- hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->Buffer, NULL);
+ DSBUFFERDESC DSBDescription{};
+ DSBDescription.dwSize = sizeof(DSBDescription);
+ DSBDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 |
+ DSBCAPS_GLOBALFOCUS;
+ DSBDescription.dwBufferBytes = device->UpdateSize * device->NumUpdates *
+ OutputType.Format.nBlockAlign;
+ DSBDescription.lpwfxFormat = &OutputType.Format;
+
+ hr = self->DS->CreateSoundBuffer(&DSBDescription, &self->Buffer, nullptr);
if(FAILED(hr) && device->FmtType == DevFmtFloat)
{
device->FmtType = DevFmtShort;
@@ -599,34 +582,37 @@ retry_open:
if(SUCCEEDED(hr))
{
- hr = IDirectSoundBuffer_QueryInterface(self->Buffer, &IID_IDirectSoundNotify, (void**)&self->Notifies);
+ void *ptr;
+ hr = self->Buffer->QueryInterface(IID_IDirectSoundNotify, &ptr);
if(SUCCEEDED(hr))
{
- DSBPOSITIONNOTIFY notifies[MAX_UPDATES];
- ALuint i;
+ auto Notifies = reinterpret_cast<IDirectSoundNotify*>(ptr);
+ self->Notifies = Notifies;
+
+ device->NumUpdates = minu(device->NumUpdates, MAX_UPDATES);
- for(i = 0;i < device->NumUpdates;++i)
+ std::array<DSBPOSITIONNOTIFY,MAX_UPDATES> nots;
+ for(ALuint i{0};i < device->NumUpdates;++i)
{
- notifies[i].dwOffset = i * device->UpdateSize *
- OutputType.Format.nBlockAlign;
- notifies[i].hEventNotify = self->NotifyEvent;
+ nots[i].dwOffset = i * device->UpdateSize * OutputType.Format.nBlockAlign;
+ nots[i].hEventNotify = self->NotifyEvent;
}
- if(IDirectSoundNotify_SetNotificationPositions(self->Notifies, device->NumUpdates, notifies) != DS_OK)
+ if(Notifies->SetNotificationPositions(device->NumUpdates, nots.data()) != DS_OK)
hr = E_FAIL;
}
}
if(FAILED(hr))
{
- if(self->Notifies != NULL)
- IDirectSoundNotify_Release(self->Notifies);
- self->Notifies = NULL;
- if(self->Buffer != NULL)
- IDirectSoundBuffer_Release(self->Buffer);
- self->Buffer = NULL;
- if(self->PrimaryBuffer != NULL)
- IDirectSoundBuffer_Release(self->PrimaryBuffer);
- self->PrimaryBuffer = NULL;
+ if(self->Notifies)
+ self->Notifies->Release();
+ self->Notifies = nullptr;
+ if(self->Buffer)
+ self->Buffer->Release();
+ self->Buffer = nullptr;
+ if(self->PrimaryBuffer)
+ self->PrimaryBuffer->Release();
+ self->PrimaryBuffer = nullptr;
return ALC_FALSE;
}
@@ -638,36 +624,38 @@ retry_open:
static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self)
{
- ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
- if(althrd_create(&self->thread, ALCdsoundPlayback_mixerProc, self) != althrd_success)
- return ALC_FALSE;
-
- return ALC_TRUE;
+ try {
+ self->killNow.store(AL_FALSE, std::memory_order_release);
+ self->thread = std::thread(ALCdsoundPlayback_mixerProc, self);
+ return ALC_TRUE;
+ }
+ catch(std::exception& e) {
+ ERR("Failed to start mixing thread: %s\n", e.what());
+ }
+ catch(...) {
+ }
+ return ALC_FALSE;
}
static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self)
{
- int res;
-
- if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
+ if(self->killNow.exchange(AL_TRUE, std::memory_order_acq_rel) || !self->thread.joinable())
return;
- althrd_join(self->thread, &res);
-
- IDirectSoundBuffer_Stop(self->Buffer);
-}
+ self->thread.join();
+ self->Buffer->Stop();
+}
-typedef struct ALCdsoundCapture {
- DERIVE_FROM_TYPE(ALCbackend);
- IDirectSoundCapture *DSC;
- IDirectSoundCaptureBuffer *DSCbuffer;
- DWORD BufferBytes;
- DWORD Cursor;
+struct ALCdsoundCapture final : public ALCbackend {
+ IDirectSoundCapture *DSC{nullptr};
+ IDirectSoundCaptureBuffer *DSCbuffer{nullptr};
+ DWORD BufferBytes{0u};
+ DWORD Cursor{0u};
- ll_ringbuffer_t *Ring;
-} ALCdsoundCapture;
+ ll_ringbuffer_t *Ring{nullptr};
+};
static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device);
static void ALCdsoundCapture_Destruct(ALCdsoundCapture *self);
@@ -686,47 +674,41 @@ DEFINE_ALCBACKEND_VTABLE(ALCdsoundCapture);
static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device)
{
+ new (self) ALCdsoundCapture{};
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
SET_VTABLE2(ALCdsoundCapture, ALCbackend, self);
-
- self->DSC = NULL;
- self->DSCbuffer = NULL;
- self->Ring = NULL;
}
static void ALCdsoundCapture_Destruct(ALCdsoundCapture *self)
{
ll_ringbuffer_free(self->Ring);
- self->Ring = NULL;
+ self->Ring = nullptr;
- if(self->DSCbuffer != NULL)
+ if(self->DSCbuffer)
{
- IDirectSoundCaptureBuffer_Stop(self->DSCbuffer);
- IDirectSoundCaptureBuffer_Release(self->DSCbuffer);
- self->DSCbuffer = NULL;
+ self->DSCbuffer->Stop();
+ self->DSCbuffer->Release();
+ self->DSCbuffer = nullptr;
}
if(self->DSC)
- IDirectSoundCapture_Release(self->DSC);
- self->DSC = NULL;
+ self->DSC->Release();
+ self->DSC = nullptr;
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+ self->~ALCdsoundCapture();
}
static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *deviceName)
{
ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- WAVEFORMATEXTENSIBLE InputType;
- DSCBUFFERDESC DSCBDescription;
- const GUID *guid = NULL;
- HRESULT hr, hrcom;
- ALuint samples;
- if(VECTOR_SIZE(CaptureDevices) == 0)
+ HRESULT hr;
+ if(CaptureDevices.empty())
{
/* Initialize COM to prevent name truncation */
- hrcom = CoInitialize(NULL);
+ HRESULT hrcom{CoInitialize(nullptr)};
hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices);
if(FAILED(hr))
ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr);
@@ -734,19 +716,19 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
CoUninitialize();
}
- if(!deviceName && VECTOR_SIZE(CaptureDevices) > 0)
+ const GUID *guid{nullptr};
+ if(!deviceName && !CaptureDevices.empty())
{
- deviceName = alstr_get_cstr(VECTOR_FRONT(CaptureDevices).name);
- guid = &VECTOR_FRONT(CaptureDevices).guid;
+ deviceName = CaptureDevices[0].name.c_str();
+ guid = &CaptureDevices[0].guid;
}
else
{
- const DevMap *iter;
-
-#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0)
- VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
-#undef MATCH_NAME
- if(iter == VECTOR_END(CaptureDevices))
+ auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
+ [deviceName](const DevMap &entry) -> bool
+ { return entry.name == deviceName; }
+ );
+ if(iter == CaptureDevices.cend())
return ALC_INVALID_VALUE;
guid = &iter->guid;
}
@@ -766,7 +748,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
break;
}
- memset(&InputType, 0, sizeof(InputType));
+ WAVEFORMATEXTENSIBLE InputType{};
switch(device->FmtChans)
{
case DevFmtMono:
@@ -841,25 +823,24 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
}
- samples = device->UpdateSize * device->NumUpdates;
+ ALuint samples{device->UpdateSize * device->NumUpdates};
samples = maxu(samples, 100 * device->Frequency / 1000);
- memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC));
- DSCBDescription.dwSize = sizeof(DSCBUFFERDESC);
+ DSCBUFFERDESC DSCBDescription{};
+ DSCBDescription.dwSize = sizeof(DSCBDescription);
DSCBDescription.dwFlags = 0;
DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign;
DSCBDescription.lpwfxFormat = &InputType.Format;
//DirectSoundCapture Init code
- hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL);
+ hr = DirectSoundCaptureCreate(guid, &self->DSC, nullptr);
if(SUCCEEDED(hr))
- hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL);
+ self->DSC->CreateCaptureBuffer(&DSCBDescription, &self->DSCbuffer, nullptr);
if(SUCCEEDED(hr))
{
self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates,
InputType.Format.nBlockAlign, false);
- if(self->Ring == NULL)
- hr = DSERR_OUTOFMEMORY;
+ if(!self->Ring) hr = DSERR_OUTOFMEMORY;
}
if(FAILED(hr))
@@ -867,13 +848,13 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
ERR("Device init failed: 0x%08lx\n", hr);
ll_ringbuffer_free(self->Ring);
- self->Ring = NULL;
- if(self->DSCbuffer != NULL)
- IDirectSoundCaptureBuffer_Release(self->DSCbuffer);
- self->DSCbuffer = NULL;
+ self->Ring = nullptr;
+ if(self->DSCbuffer)
+ self->DSCbuffer->Release();
+ self->DSCbuffer = nullptr;
if(self->DSC)
- IDirectSoundCapture_Release(self->DSC);
- self->DSC = NULL;
+ self->DSC->Release();
+ self->DSC = nullptr;
return ALC_INVALID_VALUE;
}
@@ -888,9 +869,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self)
{
- HRESULT hr;
-
- hr = IDirectSoundCaptureBuffer_Start(self->DSCbuffer, DSCBSTART_LOOPING);
+ HRESULT hr{self->DSCbuffer->Start(DSCBSTART_LOOPING)};
if(FAILED(hr))
{
ERR("start failed: 0x%08lx\n", hr);
@@ -904,9 +883,7 @@ static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self)
static void ALCdsoundCapture_stop(ALCdsoundCapture *self)
{
- HRESULT hr;
-
- hr = IDirectSoundCaptureBuffer_Stop(self->DSCbuffer);
+ HRESULT hr{self->DSCbuffer->Stop()};
if(FAILED(hr))
{
ERR("stop failed: 0x%08lx\n", hr);
@@ -917,44 +894,40 @@ static void ALCdsoundCapture_stop(ALCdsoundCapture *self)
static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples)
{
- ll_ringbuffer_read(self->Ring, buffer, samples);
+ ll_ringbuffer_read(self->Ring, reinterpret_cast<char*>(buffer), samples);
return ALC_NO_ERROR;
}
static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
{
ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- DWORD ReadCursor, LastCursor, BufferBytes, NumBytes;
- void *ReadPtr1, *ReadPtr2;
- DWORD ReadCnt1, ReadCnt2;
- DWORD FrameSize;
- HRESULT hr;
if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
- goto done;
+ return ll_ringbuffer_read_space(self->Ring);
- FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
- BufferBytes = self->BufferBytes;
- LastCursor = self->Cursor;
+ ALsizei FrameSize{FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)};
+ DWORD BufferBytes{self->BufferBytes};
+ DWORD LastCursor{self->Cursor};
- hr = IDirectSoundCaptureBuffer_GetCurrentPosition(self->DSCbuffer, NULL, &ReadCursor);
+ DWORD ReadCursor;
+ void *ReadPtr1, *ReadPtr2;
+ DWORD ReadCnt1, ReadCnt2;
+ HRESULT hr{self->DSCbuffer->GetCurrentPosition(nullptr, &ReadCursor)};
if(SUCCEEDED(hr))
{
- NumBytes = (ReadCursor-LastCursor + BufferBytes) % BufferBytes;
- if(NumBytes == 0)
- goto done;
- hr = IDirectSoundCaptureBuffer_Lock(self->DSCbuffer, LastCursor, NumBytes,
- &ReadPtr1, &ReadCnt1,
- &ReadPtr2, &ReadCnt2, 0);
+ DWORD NumBytes{(ReadCursor-LastCursor + BufferBytes) % BufferBytes};
+ if(!NumBytes) return ll_ringbuffer_read_space(self->Ring);
+ hr = self->DSCbuffer->Lock(LastCursor, NumBytes, &ReadPtr1, &ReadCnt1,
+ &ReadPtr2, &ReadCnt2, 0);
}
if(SUCCEEDED(hr))
{
- ll_ringbuffer_write(self->Ring, ReadPtr1, ReadCnt1/FrameSize);
- if(ReadPtr2 != NULL)
- ll_ringbuffer_write(self->Ring, ReadPtr2, ReadCnt2/FrameSize);
- hr = IDirectSoundCaptureBuffer_Unlock(self->DSCbuffer,
- ReadPtr1, ReadCnt1,
- ReadPtr2, ReadCnt2);
+ ll_ringbuffer_write(self->Ring, reinterpret_cast<const char*>(ReadPtr1),
+ ReadCnt1/FrameSize);
+ if(ReadPtr2 != nullptr)
+ ll_ringbuffer_write(self->Ring, reinterpret_cast<const char*>(ReadPtr2),
+ ReadCnt2/FrameSize);
+ hr = self->DSCbuffer->Unlock(ReadPtr1, ReadCnt1, ReadPtr2, ReadCnt2);
self->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes;
}
@@ -964,15 +937,14 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
aluHandleDisconnect(device, "Failure retrieving capture data: 0x%lx", hr);
}
-done:
- return (ALCuint)ll_ringbuffer_read_space(self->Ring);
+ return ll_ringbuffer_read_space(self->Ring);
}
-typedef struct ALCdsoundBackendFactory {
- DERIVE_FROM_TYPE(ALCbackendFactory);
-} ALCdsoundBackendFactory;
-#define ALCDSOUNDBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCdsoundBackendFactory, ALCbackendFactory) } }
+struct ALCdsoundBackendFactory final : public ALCbackendFactory {
+ ALCdsoundBackendFactory() noexcept;
+};
+#define ALCDSOUNDBACKENDFACTORY_INITIALIZER GET_VTABLE2(ALCdsoundBackendFactory, ALCbackendFactory)
ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void);
@@ -984,18 +956,20 @@ static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory
DEFINE_ALCBACKENDFACTORY_VTABLE(ALCdsoundBackendFactory);
+ALCdsoundBackendFactory::ALCdsoundBackendFactory() noexcept
+ : ALCbackendFactory{ALCDSOUNDBACKENDFACTORY_INITIALIZER}
+{ }
+
+
ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void)
{
- static ALCdsoundBackendFactory factory = ALCDSOUNDBACKENDFACTORY_INITIALIZER;
+ static ALCdsoundBackendFactory factory{};
return STATIC_CAST(ALCbackendFactory, &factory);
}
static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory* UNUSED(self))
{
- VECTOR_INIT(PlaybackDevices);
- VECTOR_INIT(CaptureDevices);
-
if(!DSoundLoad())
return ALC_FALSE;
return ALC_TRUE;
@@ -1003,16 +977,13 @@ static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory* UNUSED(s
static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory* UNUSED(self))
{
- clear_devlist(&PlaybackDevices);
- VECTOR_DEINIT(PlaybackDevices);
-
- clear_devlist(&CaptureDevices);
- VECTOR_DEINIT(CaptureDevices);
+ PlaybackDevices.clear();
+ CaptureDevices.clear();
#ifdef HAVE_DYNLOAD
if(ds_handle)
CloseLib(ds_handle);
- ds_handle = NULL;
+ ds_handle = nullptr;
#endif
}
@@ -1025,33 +996,36 @@ static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory*
static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
{
- HRESULT hr, hrcom;
+ auto add_device = [outnames](const DevMap &entry) -> void
+ {
+ const char *name{entry.name.c_str()};
+ size_t namelen{entry.name.length()};
+ /* +1 to also append the null char (to ensure a null-separated list and
+ * double-null terminated list).
+ */
+ alstr_append_range(outnames, name, name + namelen+1);
+ };
/* Initialize COM to prevent name truncation */
- hrcom = CoInitialize(NULL);
+ HRESULT hr;
+ HRESULT hrcom{CoInitialize(nullptr)};
switch(type)
{
-#define APPEND_OUTNAME(e) do { \
- if(!alstr_empty((e)->name)) \
- alstr_append_range(outnames, VECTOR_BEGIN((e)->name), \
- VECTOR_END((e)->name)+1); \
-} while(0)
case ALL_DEVICE_PROBE:
- clear_devlist(&PlaybackDevices);
+ PlaybackDevices.clear();
hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices);
if(FAILED(hr))
ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr);
- VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_OUTNAME);
+ std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device);
break;
case CAPTURE_DEVICE_PROBE:
- clear_devlist(&CaptureDevices);
+ CaptureDevices.clear();
hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices);
if(FAILED(hr))
ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr);
- VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_OUTNAME);
+ std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device);
break;
-#undef APPEND_OUTNAME
}
if(SUCCEEDED(hrcom))
CoUninitialize();
@@ -1063,7 +1037,7 @@ static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory
{
ALCdsoundPlayback *backend;
NEW_OBJ(backend, ALCdsoundPlayback)(device);
- if(!backend) return NULL;
+ if(!backend) return nullptr;
return STATIC_CAST(ALCbackend, backend);
}
@@ -1071,9 +1045,9 @@ static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory
{
ALCdsoundCapture *backend;
NEW_OBJ(backend, ALCdsoundCapture)(device);
- if(!backend) return NULL;
+ if(!backend) return nullptr;
return STATIC_CAST(ALCbackend, backend);
}
- return NULL;
+ return nullptr;
}
diff --git a/Alc/backends/jack.c b/Alc/backends/jack.c
index fdbe93f2..8f934687 100644
--- a/Alc/backends/jack.c
+++ b/Alc/backends/jack.c
@@ -68,6 +68,7 @@ JACK_FUNCS(MAKE_FUNC);
static __typeof(jack_error_callback) * pjack_error_callback;
#undef MAKE_FUNC
+#ifndef IN_IDE_PARSER
#define jack_client_open pjack_client_open
#define jack_client_close pjack_client_close
#define jack_client_name_size pjack_client_name_size
@@ -89,6 +90,7 @@ static __typeof(jack_error_callback) * pjack_error_callback;
#define jack_get_buffer_size pjack_get_buffer_size
#define jack_error_callback (*pjack_error_callback)
#endif
+#endif
static jack_options_t ClientOptions = JackNullOption;
@@ -266,7 +268,7 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg)
todo = minu(numframes, data[0].len);
for(c = 0;c < numchans;c++)
{
- const ALfloat *restrict in = ((ALfloat*)data[0].buf) + c;
+ const ALfloat *RESTRICT in = ((ALfloat*)data[0].buf) + c;
for(i = 0;(jack_nframes_t)i < todo;i++)
out[c][i] = in[i*numchans];
out[c] += todo;
@@ -278,7 +280,7 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg)
{
for(c = 0;c < numchans;c++)
{
- const ALfloat *restrict in = ((ALfloat*)data[1].buf) + c;
+ const ALfloat *RESTRICT in = ((ALfloat*)data[1].buf) + c;
for(i = 0;(jack_nframes_t)i < todo;i++)
out[c][i] = in[i*numchans];
out[c] += todo;
diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c
index 6a6cfa31..7bc3c230 100644
--- a/Alc/backends/portaudio.c
+++ b/Alc/backends/portaudio.c
@@ -53,6 +53,7 @@ MAKE_FUNC(Pa_GetDefaultInputDevice);
MAKE_FUNC(Pa_GetStreamInfo);
#undef MAKE_FUNC
+#ifndef IN_IDE_PARSER
#define Pa_Initialize pPa_Initialize
#define Pa_Terminate pPa_Terminate
#define Pa_GetErrorText pPa_GetErrorText
@@ -64,6 +65,7 @@ MAKE_FUNC(Pa_GetStreamInfo);
#define Pa_GetDefaultInputDevice pPa_GetDefaultInputDevice
#define Pa_GetStreamInfo pPa_GetStreamInfo
#endif
+#endif
static ALCboolean pa_load(void)
{
diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.cpp
index b34d7abc..e2845032 100644
--- a/Alc/backends/pulseaudio.c
+++ b/Alc/backends/pulseaudio.cpp
@@ -23,10 +23,16 @@
#include <string.h>
+#include <array>
+#include <string>
+#include <vector>
+#include <atomic>
+#include <thread>
+#include <algorithm>
+
#include "alMain.h"
#include "alu.h"
#include "alconfig.h"
-#include "threads.h"
#include "compat.h"
#include "backends/base.h"
@@ -35,9 +41,11 @@
#if PA_API_VERSION == 12
+namespace {
+
#ifdef HAVE_DYNLOAD
-static void *pa_handle;
-#define MAKE_FUNC(x) static __typeof(x) * p##x
+void *pa_handle;
+#define MAKE_FUNC(x) decltype(x) * p##x
MAKE_FUNC(pa_context_unref);
MAKE_FUNC(pa_sample_spec_valid);
MAKE_FUNC(pa_frame_size);
@@ -107,6 +115,7 @@ MAKE_FUNC(pa_stream_set_buffer_attr_callback);
MAKE_FUNC(pa_stream_begin_write);
#undef MAKE_FUNC
+#ifndef IN_IDE_PARSER
#define pa_context_unref ppa_context_unref
#define pa_sample_spec_valid ppa_sample_spec_valid
#define pa_frame_size ppa_frame_size
@@ -174,16 +183,17 @@ MAKE_FUNC(pa_stream_begin_write);
#define pa_channel_map_superset ppa_channel_map_superset
#define pa_stream_set_buffer_attr_callback ppa_stream_set_buffer_attr_callback
#define pa_stream_begin_write ppa_stream_begin_write
+#endif /* IN_IDE_PARSER */
#endif
-static ALCboolean pulse_load(void)
+ALCboolean pulse_load(void)
{
- ALCboolean ret = ALC_TRUE;
+ ALCboolean ret{ALC_TRUE};
#ifdef HAVE_DYNLOAD
if(!pa_handle)
{
- al_string missing_funcs = AL_STRING_INIT_STATIC();
+ std::string missing_funcs;
#ifdef _WIN32
#define PALIB "libpulse-0.dll"
@@ -200,10 +210,10 @@ static ALCboolean pulse_load(void)
}
#define LOAD_FUNC(x) do { \
- p##x = GetSymbol(pa_handle, #x); \
+ p##x = reinterpret_cast<decltype(p##x)>(GetSymbol(pa_handle, #x)); \
if(!(p##x)) { \
ret = ALC_FALSE; \
- alstr_append_cstr(&missing_funcs, "\n" #x); \
+ missing_funcs += "\n" #x; \
} \
} while(0)
LOAD_FUNC(pa_context_unref);
@@ -277,50 +287,112 @@ static ALCboolean pulse_load(void)
if(ret == ALC_FALSE)
{
- WARN("Missing expected functions:%s\n", alstr_get_cstr(missing_funcs));
+ WARN("Missing expected functions:%s\n", missing_funcs.c_str());
CloseLib(pa_handle);
- pa_handle = NULL;
+ pa_handle = nullptr;
}
- alstr_reset(&missing_funcs);
}
#endif /* HAVE_DYNLOAD */
return ret;
}
+/* *grumble* Don't use enums for bitflags. */
+inline pa_stream_flags_t operator|(pa_stream_flags_t lhs, pa_stream_flags_t rhs)
+{ return pa_stream_flags_t(int(lhs) | int(rhs)); }
+
+inline pa_stream_flags_t operator|=(pa_stream_flags_t &lhs, pa_stream_flags_t rhs)
+{
+ lhs = pa_stream_flags_t(int(lhs) | int(rhs));
+ return lhs;
+}
+
+inline pa_context_flags_t operator|=(pa_context_flags_t &lhs, pa_context_flags_t rhs)
+{
+ lhs = pa_context_flags_t(int(lhs) | int(rhs));
+ return lhs;
+}
+
+
+class palock_guard {
+ pa_threaded_mainloop *mLoop;
+
+public:
+ explicit palock_guard(pa_threaded_mainloop *loop) : mLoop(loop)
+ { pa_threaded_mainloop_lock(mLoop); }
+ ~palock_guard() { pa_threaded_mainloop_unlock(mLoop); }
+
+ palock_guard(const palock_guard&) = delete;
+ palock_guard& operator=(const palock_guard&) = delete;
+};
+
+class unique_palock {
+ pa_threaded_mainloop *mLoop{nullptr};
+ bool mLocked{false};
+
+public:
+ unique_palock() noexcept = default;
+ explicit unique_palock(pa_threaded_mainloop *loop) : mLoop(loop)
+ {
+ pa_threaded_mainloop_lock(mLoop);
+ mLocked = true;
+ }
+ unique_palock(unique_palock&& rhs) : mLoop(rhs.mLoop), mLocked(rhs.mLocked)
+ { rhs.mLoop = nullptr; rhs.mLocked = false; }
+ ~unique_palock() { if(mLocked) pa_threaded_mainloop_unlock(mLoop); }
+
+ unique_palock& operator=(const unique_palock&) = delete;
+ unique_palock& operator=(unique_palock&& rhs)
+ {
+ if(mLocked)
+ pa_threaded_mainloop_unlock(mLoop);
+ mLoop = rhs.mLoop; rhs.mLoop = nullptr;
+ mLocked = rhs.mLocked; rhs.mLocked = false;
+ return *this;
+ }
+
+ void lock()
+ {
+ pa_threaded_mainloop_lock(mLoop);
+ mLocked = true;
+ }
+ void unlock()
+ {
+ mLocked = false;
+ pa_threaded_mainloop_unlock(mLoop);
+ }
+};
+
+
/* Global flags and properties */
-static pa_context_flags_t pulse_ctx_flags;
-static pa_proplist *prop_filter;
+pa_context_flags_t pulse_ctx_flags;
+pa_proplist *prop_filter;
/* PulseAudio Event Callbacks */
-static void context_state_callback(pa_context *context, void *pdata)
+void context_state_callback(pa_context *context, void *pdata)
{
- pa_threaded_mainloop *loop = pdata;
- pa_context_state_t state;
-
- state = pa_context_get_state(context);
+ auto loop = reinterpret_cast<pa_threaded_mainloop*>(pdata);
+ pa_context_state_t state{pa_context_get_state(context)};
if(state == PA_CONTEXT_READY || !PA_CONTEXT_IS_GOOD(state))
pa_threaded_mainloop_signal(loop, 0);
}
-static void stream_state_callback(pa_stream *stream, void *pdata)
+void stream_state_callback(pa_stream *stream, void *pdata)
{
- pa_threaded_mainloop *loop = pdata;
- pa_stream_state_t state;
-
- state = pa_stream_get_state(stream);
+ auto loop = reinterpret_cast<pa_threaded_mainloop*>(pdata);
+ pa_stream_state_t state{pa_stream_get_state(stream)};
if(state == PA_STREAM_READY || !PA_STREAM_IS_GOOD(state))
pa_threaded_mainloop_signal(loop, 0);
}
-static void stream_success_callback(pa_stream *UNUSED(stream), int UNUSED(success), void *pdata)
+void stream_success_callback(pa_stream *UNUSED(stream), int UNUSED(success), void *pdata)
{
- pa_threaded_mainloop *loop = pdata;
+ auto loop = reinterpret_cast<pa_threaded_mainloop*>(pdata);
pa_threaded_mainloop_signal(loop, 0);
}
-static void wait_for_operation(pa_operation *op, pa_threaded_mainloop *loop)
+void wait_for_operation(pa_operation *op, pa_threaded_mainloop *loop)
{
if(op)
{
@@ -331,30 +403,29 @@ static void wait_for_operation(pa_operation *op, pa_threaded_mainloop *loop)
}
-static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent)
+pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent)
{
- const char *name = "OpenAL Soft";
- al_string binname = AL_STRING_INIT_STATIC();
- pa_context_state_t state;
- pa_context *context;
- int err;
+ const char *name{"OpenAL Soft"};
+ al_string binname{AL_STRING_INIT_STATIC()};
- GetProcBinary(NULL, &binname);
+ GetProcBinary(nullptr, &binname);
if(!alstr_empty(binname))
name = alstr_get_cstr(binname);
- context = pa_context_new(pa_threaded_mainloop_get_api(loop), name);
+ pa_context *context{pa_context_new(pa_threaded_mainloop_get_api(loop), name)};
if(!context)
{
ERR("pa_context_new() failed\n");
alstr_reset(&binname);
- return NULL;
+ return nullptr;
}
pa_context_set_state_callback(context, context_state_callback, loop);
- if((err=pa_context_connect(context, NULL, pulse_ctx_flags, NULL)) >= 0)
+ int err;
+ if((err=pa_context_connect(context, nullptr, pulse_ctx_flags, nullptr)) >= 0)
{
+ pa_context_state_t state;
while((state=pa_context_get_state(context)) != PA_CONTEXT_READY)
{
if(!PA_CONTEXT_IS_GOOD(state))
@@ -367,14 +438,14 @@ static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent)
pa_threaded_mainloop_wait(loop);
}
}
- pa_context_set_state_callback(context, NULL, NULL);
+ pa_context_set_state_callback(context, nullptr, nullptr);
if(err < 0)
{
if(!silent)
ERR("Context did not connect: %s\n", pa_strerror(err));
pa_context_unref(context);
- context = NULL;
+ context = nullptr;
}
alstr_reset(&binname);
@@ -382,162 +453,152 @@ static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent)
}
-static ALCboolean pulse_open(pa_threaded_mainloop **loop, pa_context **context,
- void(*state_cb)(pa_context*,void*), void *ptr)
+using MainloopContextPair = std::pair<pa_threaded_mainloop*,pa_context*>;
+MainloopContextPair pulse_open(void(*state_cb)(pa_context*,void*), void *ptr)
{
- if(!(*loop = pa_threaded_mainloop_new()))
+ pa_threaded_mainloop *loop{pa_threaded_mainloop_new()};
+ if(UNLIKELY(!loop))
{
ERR("pa_threaded_mainloop_new() failed!\n");
- return ALC_FALSE;
+ return {nullptr, nullptr};
}
- if(pa_threaded_mainloop_start(*loop) < 0)
+ if(UNLIKELY(pa_threaded_mainloop_start(loop) < 0))
{
ERR("pa_threaded_mainloop_start() failed\n");
- goto error;
+ pa_threaded_mainloop_free(loop);
+ return {nullptr, nullptr};
}
- pa_threaded_mainloop_lock(*loop);
-
- *context = connect_context(*loop, AL_FALSE);
- if(!*context)
+ unique_palock palock{loop};
+ pa_context *context{connect_context(loop, AL_FALSE)};
+ if(UNLIKELY(!context))
{
- pa_threaded_mainloop_unlock(*loop);
- pa_threaded_mainloop_stop(*loop);
- goto error;
+ palock = unique_palock{};
+ pa_threaded_mainloop_stop(loop);
+ pa_threaded_mainloop_free(loop);
+ return {nullptr, nullptr};
}
- pa_context_set_state_callback(*context, state_cb, ptr);
-
- pa_threaded_mainloop_unlock(*loop);
- return ALC_TRUE;
-
-error:
- pa_threaded_mainloop_free(*loop);
- *loop = NULL;
-
- return ALC_FALSE;
+ pa_context_set_state_callback(context, state_cb, ptr);
+ return {loop, context};
}
-static void pulse_close(pa_threaded_mainloop *loop, pa_context *context, pa_stream *stream)
+void pulse_close(pa_threaded_mainloop *loop, pa_context *context, pa_stream *stream)
{
- pa_threaded_mainloop_lock(loop);
+ { palock_guard _{loop};
+ if(stream)
+ {
+ pa_stream_set_state_callback(stream, nullptr, nullptr);
+ pa_stream_set_moved_callback(stream, nullptr, nullptr);
+ pa_stream_set_write_callback(stream, nullptr, nullptr);
+ pa_stream_set_buffer_attr_callback(stream, nullptr, nullptr);
+ pa_stream_disconnect(stream);
+ pa_stream_unref(stream);
+ }
- if(stream)
- {
- pa_stream_set_state_callback(stream, NULL, NULL);
- pa_stream_set_moved_callback(stream, NULL, NULL);
- pa_stream_set_write_callback(stream, NULL, NULL);
- pa_stream_set_buffer_attr_callback(stream, NULL, NULL);
- pa_stream_disconnect(stream);
- pa_stream_unref(stream);
+ pa_context_disconnect(context);
+ pa_context_unref(context);
}
- pa_context_disconnect(context);
- pa_context_unref(context);
-
- pa_threaded_mainloop_unlock(loop);
-
pa_threaded_mainloop_stop(loop);
pa_threaded_mainloop_free(loop);
}
-typedef struct {
- al_string name;
- al_string device_name;
-} DevMap;
-TYPEDEF_VECTOR(DevMap, vector_DevMap)
+struct DevMap {
+ std::string name;
+ std::string device_name;
-static vector_DevMap PlaybackDevices;
-static vector_DevMap CaptureDevices;
+ template<typename StrT0, typename StrT1>
+ DevMap(StrT0&& name_, StrT1&& devname_)
+ : name{std::forward<StrT0>(name_)}, device_name{std::forward<StrT1>(devname_)}
+ { }
+};
-static void clear_devlist(vector_DevMap *list)
+bool checkName(const std::vector<DevMap> &list, const std::string &name)
{
-#define DEINIT_STRS(i) (AL_STRING_DEINIT((i)->name),AL_STRING_DEINIT((i)->device_name))
- VECTOR_FOR_EACH(DevMap, *list, DEINIT_STRS);
-#undef DEINIT_STRS
- VECTOR_RESIZE(*list, 0, 0);
+ return std::find_if(list.cbegin(), list.cend(),
+ [&name](const DevMap &entry) -> bool
+ { return entry.name == name; }
+ ) != list.cend();
}
+std::vector<DevMap> PlaybackDevices;
+std::vector<DevMap> CaptureDevices;
-typedef struct ALCpulsePlayback {
- DERIVE_FROM_TYPE(ALCbackend);
+} // namespace
- al_string device_name;
+
+struct PulsePlayback final : public ALCbackend {
+ std::string device_name;
pa_buffer_attr attr;
pa_sample_spec spec;
- pa_threaded_mainloop *loop;
-
- pa_stream *stream;
- pa_context *context;
-
- ATOMIC(ALenum) killNow;
- althrd_t thread;
-} ALCpulsePlayback;
-
-static void ALCpulsePlayback_deviceCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
-static void ALCpulsePlayback_probeDevices(void);
-
-static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata);
-static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata);
-static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata);
-static void ALCpulsePlayback_streamWriteCallback(pa_stream *p, size_t nbytes, void *userdata);
-static void ALCpulsePlayback_sinkInfoCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
-static void ALCpulsePlayback_sinkNameCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
-static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata);
-static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, pa_threaded_mainloop *loop,
- pa_context *context, pa_stream_flags_t flags,
- pa_buffer_attr *attr, pa_sample_spec *spec,
- pa_channel_map *chanmap);
-static int ALCpulsePlayback_mixerProc(void *ptr);
-
-static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device);
-static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self);
-static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name);
-static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self);
-static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self);
-static void ALCpulsePlayback_stop(ALCpulsePlayback *self);
-static DECLARE_FORWARD2(ALCpulsePlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
-static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, ALCuint, availableSamples)
-static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self);
-static void ALCpulsePlayback_lock(ALCpulsePlayback *self);
-static void ALCpulsePlayback_unlock(ALCpulsePlayback *self);
-DECLARE_DEFAULT_ALLOCATORS(ALCpulsePlayback)
-
-DEFINE_ALCBACKEND_VTABLE(ALCpulsePlayback);
-
-
-static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device)
+ pa_threaded_mainloop *loop{nullptr};
+
+ pa_stream *stream{nullptr};
+ pa_context *context{nullptr};
+
+ std::atomic<ALenum> killNow{ALC_TRUE};
+ std::thread thread;
+};
+
+static void PulsePlayback_deviceCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
+static void PulsePlayback_probeDevices(void);
+
+static void PulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata);
+static void PulsePlayback_contextStateCallback(pa_context *context, void *pdata);
+static void PulsePlayback_streamStateCallback(pa_stream *stream, void *pdata);
+static void PulsePlayback_streamWriteCallback(pa_stream *p, size_t nbytes, void *userdata);
+static void PulsePlayback_sinkInfoCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
+static void PulsePlayback_sinkNameCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
+static void PulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata);
+static pa_stream *PulsePlayback_connectStream(const char *device_name, pa_threaded_mainloop *loop,
+ pa_context *context, pa_stream_flags_t flags,
+ pa_buffer_attr *attr, pa_sample_spec *spec,
+ pa_channel_map *chanmap);
+static int PulsePlayback_mixerProc(PulsePlayback *self);
+
+static void PulsePlayback_Construct(PulsePlayback *self, ALCdevice *device);
+static void PulsePlayback_Destruct(PulsePlayback *self);
+static ALCenum PulsePlayback_open(PulsePlayback *self, const ALCchar *name);
+static ALCboolean PulsePlayback_reset(PulsePlayback *self);
+static ALCboolean PulsePlayback_start(PulsePlayback *self);
+static void PulsePlayback_stop(PulsePlayback *self);
+static DECLARE_FORWARD2(PulsePlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
+static DECLARE_FORWARD(PulsePlayback, ALCbackend, ALCuint, availableSamples)
+static ClockLatency PulsePlayback_getClockLatency(PulsePlayback *self);
+static void PulsePlayback_lock(PulsePlayback *self);
+static void PulsePlayback_unlock(PulsePlayback *self);
+DECLARE_DEFAULT_ALLOCATORS(PulsePlayback)
+
+DEFINE_ALCBACKEND_VTABLE(PulsePlayback);
+
+
+static void PulsePlayback_Construct(PulsePlayback *self, ALCdevice *device)
{
+ new (self) PulsePlayback();
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
- SET_VTABLE2(ALCpulsePlayback, ALCbackend, self);
-
- self->loop = NULL;
- AL_STRING_INIT(self->device_name);
- ATOMIC_INIT(&self->killNow, AL_TRUE);
+ SET_VTABLE2(PulsePlayback, ALCbackend, self);
}
-static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self)
+static void PulsePlayback_Destruct(PulsePlayback *self)
{
if(self->loop)
{
pulse_close(self->loop, self->context, self->stream);
- self->loop = NULL;
- self->context = NULL;
- self->stream = NULL;
+ self->loop = nullptr;
+ self->context = nullptr;
+ self->stream = nullptr;
}
- AL_STRING_DEINIT(self->device_name);
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+ self->~PulsePlayback();
}
-static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
+static void PulsePlayback_deviceCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
{
- pa_threaded_mainloop *loop = pdata;
- const DevMap *iter;
- DevMap entry;
- int count;
+ auto loop = reinterpret_cast<pa_threaded_mainloop*>(pdata);
if(eol)
{
@@ -545,86 +606,74 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p
return;
}
-#define MATCH_INFO_NAME(iter) (alstr_cmp_cstr((iter)->device_name, info->name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_INFO_NAME);
- if(iter != VECTOR_END(PlaybackDevices)) return;
-#undef MATCH_INFO_NAME
-
- AL_STRING_INIT(entry.name);
- AL_STRING_INIT(entry.device_name);
-
- alstr_copy_cstr(&entry.device_name, info->name);
+ /* Skip this device is if it's already in the list. */
+ if(std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
+ [info](const DevMap &entry) -> bool
+ { return entry.device_name == info->name; }
+ ) != PlaybackDevices.cend())
+ return;
- count = 0;
- while(1)
+ /* Make sure the display name (description) is unique. Append a number
+ * counter as needed.
+ */
+ int count{1};
+ std::string newname{info->description};
+ while(checkName(PlaybackDevices, newname))
{
- alstr_copy_cstr(&entry.name, info->description);
- if(count != 0)
- {
- char str[64];
- snprintf(str, sizeof(str), " #%d", count+1);
- alstr_append_cstr(&entry.name, str);
- }
-
-#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_ENTRY);
- if(iter == VECTOR_END(PlaybackDevices)) break;
-#undef MATCH_ENTRY
- count++;
+ newname = info->description;
+ newname += " #";
+ newname += std::to_string(++count);
}
+ PlaybackDevices.emplace_back(std::move(newname), info->name);
+ DevMap &newentry = PlaybackDevices.back();
- TRACE("Got device \"%s\", \"%s\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.device_name));
-
- VECTOR_PUSH_BACK(PlaybackDevices, entry);
+ TRACE("Got device \"%s\", \"%s\"\n", newentry.name.c_str(), newentry.device_name.c_str());
}
-static void ALCpulsePlayback_probeDevices(void)
+static void PulsePlayback_probeDevices(void)
{
- pa_threaded_mainloop *loop;
+ PlaybackDevices.clear();
- clear_devlist(&PlaybackDevices);
-
- if((loop=pa_threaded_mainloop_new()) &&
- pa_threaded_mainloop_start(loop) >= 0)
+ pa_threaded_mainloop *loop{pa_threaded_mainloop_new()};
+ if(loop && pa_threaded_mainloop_start(loop) >= 0)
{
- pa_context *context;
+ unique_palock palock{loop};
- pa_threaded_mainloop_lock(loop);
- context = connect_context(loop, AL_FALSE);
+ pa_context *context{connect_context(loop, AL_FALSE)};
if(context)
{
- pa_operation *o;
- pa_stream_flags_t flags;
- pa_sample_spec spec;
- pa_stream *stream;
-
- flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
- PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE;
+ pa_stream_flags_t flags{PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
+ PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE};
+ pa_sample_spec spec;
spec.format = PA_SAMPLE_S16NE;
spec.rate = 44100;
spec.channels = 2;
- stream = ALCpulsePlayback_connectStream(NULL, loop, context, flags,
- NULL, &spec, NULL);
+ pa_stream *stream{PulsePlayback_connectStream(nullptr,
+ loop, context, flags, nullptr, &spec, nullptr
+ )};
if(stream)
{
- o = pa_context_get_sink_info_by_name(context, pa_stream_get_device_name(stream),
- ALCpulsePlayback_deviceCallback, loop);
- wait_for_operation(o, loop);
+ pa_operation *op{pa_context_get_sink_info_by_name(context,
+ pa_stream_get_device_name(stream), PulsePlayback_deviceCallback, loop
+ )};
+ wait_for_operation(op, loop);
pa_stream_disconnect(stream);
pa_stream_unref(stream);
- stream = NULL;
+ stream = nullptr;
}
- o = pa_context_get_sink_info_list(context, ALCpulsePlayback_deviceCallback, loop);
- wait_for_operation(o, loop);
+ pa_operation *op{pa_context_get_sink_info_list(context,
+ PulsePlayback_deviceCallback, loop
+ )};
+ wait_for_operation(op, loop);
pa_context_disconnect(context);
pa_context_unref(context);
}
- pa_threaded_mainloop_unlock(loop);
+ palock = unique_palock{};
pa_threaded_mainloop_stop(loop);
}
if(loop)
@@ -632,9 +681,9 @@ static void ALCpulsePlayback_probeDevices(void)
}
-static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata)
+static void PulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata)
{
- ALCpulsePlayback *self = pdata;
+ auto self = reinterpret_cast<PulsePlayback*>(pdata);
self->attr = *pa_stream_get_buffer_attr(stream);
TRACE("minreq=%d, tlength=%d, prebuf=%d\n", self->attr.minreq, self->attr.tlength, self->attr.prebuf);
@@ -645,9 +694,9 @@ static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata)
*/
}
-static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata)
+static void PulsePlayback_contextStateCallback(pa_context *context, void *pdata)
{
- ALCpulsePlayback *self = pdata;
+ auto self = reinterpret_cast<PulsePlayback*>(pdata);
if(pa_context_get_state(context) == PA_CONTEXT_FAILED)
{
ERR("Received context failure!\n");
@@ -656,9 +705,9 @@ static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pda
pa_threaded_mainloop_signal(self->loop, 0);
}
-static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata)
+static void PulsePlayback_streamStateCallback(pa_stream *stream, void *pdata)
{
- ALCpulsePlayback *self = pdata;
+ auto self = reinterpret_cast<PulsePlayback*>(pdata);
if(pa_stream_get_state(stream) == PA_STREAM_FAILED)
{
ERR("Received stream failure!\n");
@@ -667,18 +716,19 @@ static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata)
pa_threaded_mainloop_signal(self->loop, 0);
}
-static void ALCpulsePlayback_streamWriteCallback(pa_stream* UNUSED(p), size_t UNUSED(nbytes), void *pdata)
+static void PulsePlayback_streamWriteCallback(pa_stream* UNUSED(p), size_t UNUSED(nbytes), void *pdata)
{
- ALCpulsePlayback *self = pdata;
+ auto self = reinterpret_cast<PulsePlayback*>(pdata);
pa_threaded_mainloop_signal(self->loop, 0);
}
-static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
+static void PulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
{
- static const struct {
- enum DevFmtChannels chans;
+ struct ChannelMap {
+ DevFmtChannels chans;
pa_channel_map map;
- } chanmaps[] = {
+ };
+ static constexpr std::array<ChannelMap,7> chanmaps{{
{ DevFmtX71, { 8, {
PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
@@ -709,10 +759,8 @@ static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const
PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT
} } },
{ DevFmtMono, { 1, {PA_CHANNEL_POSITION_MONO} } }
- };
- ALCpulsePlayback *self = pdata;
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- size_t i;
+ }};
+ auto self = reinterpret_cast<PulsePlayback*>(pdata);
if(eol)
{
@@ -720,18 +768,19 @@ static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const
return;
}
- for(i = 0;i < COUNTOF(chanmaps);i++)
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
+ auto chanmap = std::find_if(chanmaps.cbegin(), chanmaps.cend(),
+ [info](const ChannelMap &chanmap) -> bool
+ { return pa_channel_map_superset(&info->channel_map, &chanmap.map); }
+ );
+ if(chanmap != chanmaps.cend())
{
- if(pa_channel_map_superset(&info->channel_map, &chanmaps[i].map))
- {
- if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
- device->FmtChans = chanmaps[i].chans;
- break;
- }
+ if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
+ device->FmtChans = chanmap->chans;
}
- if(i == COUNTOF(chanmaps))
+ else
{
- char chanmap_str[PA_CHANNEL_MAP_SNPRINT_MAX] = "";
+ char chanmap_str[PA_CHANNEL_MAP_SNPRINT_MAX]{};
pa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map);
WARN("Failed to find format for channel map:\n %s\n", chanmap_str);
}
@@ -743,10 +792,9 @@ static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const
device->FmtChans == DevFmtStereo);
}
-static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
+static void PulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
{
- ALCpulsePlayback *self = pdata;
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+ auto self = reinterpret_cast<PulsePlayback*>(pdata);
if(eol)
{
@@ -754,90 +802,84 @@ static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const
return;
}
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
alstr_copy_cstr(&device->DeviceName, info->description);
}
-static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata)
+static void PulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata)
{
- ALCpulsePlayback *self = pdata;
+ auto self = reinterpret_cast<PulsePlayback*>(pdata);
- alstr_copy_cstr(&self->device_name, pa_stream_get_device_name(stream));
+ self->device_name = pa_stream_get_device_name(stream);
- TRACE("Stream moved to %s\n", alstr_get_cstr(self->device_name));
+ TRACE("Stream moved to %s\n", self->device_name.c_str());
}
-static pa_stream *ALCpulsePlayback_connectStream(const char *device_name,
+static pa_stream *PulsePlayback_connectStream(const char *device_name,
pa_threaded_mainloop *loop, pa_context *context,
pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec,
pa_channel_map *chanmap)
{
- pa_stream_state_t state;
- pa_stream *stream;
-
if(!device_name)
{
device_name = getenv("ALSOFT_PULSE_DEFAULT");
if(device_name && !device_name[0])
- device_name = NULL;
+ device_name = nullptr;
}
- stream = pa_stream_new_with_proplist(context, "Playback Stream", spec, chanmap, prop_filter);
+ pa_stream *stream{pa_stream_new_with_proplist(context,
+ "Playback Stream", spec, chanmap, prop_filter
+ )};
if(!stream)
{
ERR("pa_stream_new_with_proplist() failed: %s\n", pa_strerror(pa_context_errno(context)));
- return NULL;
+ return nullptr;
}
pa_stream_set_state_callback(stream, stream_state_callback, loop);
- if(pa_stream_connect_playback(stream, device_name, attr, flags, NULL, NULL) < 0)
+ if(pa_stream_connect_playback(stream, device_name, attr, flags, nullptr, nullptr) < 0)
{
ERR("Stream did not connect: %s\n", pa_strerror(pa_context_errno(context)));
pa_stream_unref(stream);
- return NULL;
+ return nullptr;
}
+ pa_stream_state_t state;
while((state=pa_stream_get_state(stream)) != PA_STREAM_READY)
{
if(!PA_STREAM_IS_GOOD(state))
{
ERR("Stream did not get ready: %s\n", pa_strerror(pa_context_errno(context)));
pa_stream_unref(stream);
- return NULL;
+ return nullptr;
}
pa_threaded_mainloop_wait(loop);
}
- pa_stream_set_state_callback(stream, NULL, NULL);
+ pa_stream_set_state_callback(stream, nullptr, nullptr);
return stream;
}
-static int ALCpulsePlayback_mixerProc(void *ptr)
+static int PulsePlayback_mixerProc(PulsePlayback *self)
{
- ALCpulsePlayback *self = ptr;
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- ALuint buffer_size;
- size_t frame_size;
- ssize_t len;
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
SetRTPriority();
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
- pa_threaded_mainloop_lock(self->loop);
- frame_size = pa_frame_size(&self->spec);
+ unique_palock palock{self->loop};
+ size_t frame_size{pa_frame_size(&self->spec)};
- while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+ while(!self->killNow.load(std::memory_order_acquire) &&
ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
{
- void *buf;
- int ret;
-
- len = pa_stream_writable_size(self->stream);
- if(len < 0)
+ ssize_t len{static_cast<ssize_t>(pa_stream_writable_size(self->stream))};
+ if(UNLIKELY(len < 0))
{
ERR("Failed to get writable size: %ld", (long)len);
aluHandleDisconnect(device, "Failed to get writable size: %ld", (long)len);
@@ -848,20 +890,20 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
* case the server increased it since starting playback. Also round up
* the number of writable periods if it's not an integer count.
*/
- buffer_size = maxu((self->attr.tlength + self->attr.minreq/2) / self->attr.minreq, 2) *
- self->attr.minreq;
+ ALint buffer_size{static_cast<int32_t>(self->attr.minreq) * maxi(
+ (self->attr.tlength + self->attr.minreq/2) / self->attr.minreq, 2
+ )};
/* NOTE: This assumes pa_stream_writable_size returns between 0 and
* tlength, else there will be more latency than intended.
*/
- len = mini(len - (ssize_t)self->attr.tlength, 0) + buffer_size;
- if(len < (int32_t)self->attr.minreq)
+ len = buffer_size - maxi((ssize_t)self->attr.tlength - len, 0);
+ if(len < self->attr.minreq)
{
if(pa_stream_is_corked(self->stream))
{
- pa_operation *o;
- o = pa_stream_cork(self->stream, 0, NULL, NULL);
- if(o) pa_operation_unref(o);
+ pa_operation *op{pa_stream_cork(self->stream, 0, nullptr, nullptr)};
+ if(op) pa_operation_unref(op);
}
pa_threaded_mainloop_wait(self->loop);
continue;
@@ -870,122 +912,111 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
len -= len%self->attr.minreq;
len -= len%frame_size;
- buf = pa_xmalloc(len);
-
+ void *buf{pa_xmalloc(len)};
aluMixData(device, buf, len/frame_size);
- ret = pa_stream_write(self->stream, buf, len, pa_xfree, 0, PA_SEEK_RELATIVE);
- if(ret != PA_OK) ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
+ int ret{pa_stream_write(self->stream, buf, len, pa_xfree, 0, PA_SEEK_RELATIVE)};
+ if(UNLIKELY(ret != PA_OK))
+ ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
}
- pa_threaded_mainloop_unlock(self->loop);
return 0;
}
-static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name)
+static ALCenum PulsePlayback_open(PulsePlayback *self, const ALCchar *name)
{
- const_al_string dev_name = AL_STRING_INIT_STATIC();
- const char *pulse_name = NULL;
- pa_stream_flags_t flags;
- pa_sample_spec spec;
+ const char *pulse_name{nullptr};
+ const char *dev_name{nullptr};
if(name)
{
- const DevMap *iter;
+ if(PlaybackDevices.empty())
+ PulsePlayback_probeDevices();
- if(VECTOR_SIZE(PlaybackDevices) == 0)
- ALCpulsePlayback_probeDevices();
-
-#define MATCH_NAME(iter) (alstr_cmp_cstr((iter)->name, name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
-#undef MATCH_NAME
- if(iter == VECTOR_END(PlaybackDevices))
+ auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
+ [name](const DevMap &entry) -> bool
+ { return entry.name == name; }
+ );
+ if(iter == PlaybackDevices.cend())
return ALC_INVALID_VALUE;
- pulse_name = alstr_get_cstr(iter->device_name);
- dev_name = iter->name;
+ pulse_name = iter->device_name.c_str();
+ dev_name = iter->name.c_str();
}
- if(!pulse_open(&self->loop, &self->context, ALCpulsePlayback_contextStateCallback, self))
- return ALC_INVALID_VALUE;
+ std::tie(self->loop, self->context) = pulse_open(PulsePlayback_contextStateCallback, self);
+ if(!self->loop) return ALC_INVALID_VALUE;
- pa_threaded_mainloop_lock(self->loop);
+ unique_palock palock{self->loop};
- flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
- PA_STREAM_FIX_CHANNELS;
- if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0))
+ pa_stream_flags_t flags{PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
+ PA_STREAM_FIX_CHANNELS};
+ if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", 0))
flags |= PA_STREAM_DONT_MOVE;
+ pa_sample_spec spec{};
spec.format = PA_SAMPLE_S16NE;
spec.rate = 44100;
spec.channels = 2;
TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)");
- self->stream = ALCpulsePlayback_connectStream(pulse_name, self->loop, self->context,
- flags, NULL, &spec, NULL);
+ self->stream = PulsePlayback_connectStream(pulse_name, self->loop, self->context,
+ flags, nullptr, &spec, nullptr);
if(!self->stream)
{
- pa_threaded_mainloop_unlock(self->loop);
+ palock = unique_palock{};
pulse_close(self->loop, self->context, self->stream);
- self->loop = NULL;
- self->context = NULL;
+ self->loop = nullptr;
+ self->context = nullptr;
return ALC_INVALID_VALUE;
}
- pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self);
+ pa_stream_set_moved_callback(self->stream, PulsePlayback_streamMovedCallback, self);
- alstr_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream));
- if(alstr_empty(dev_name))
+ self->device_name = pa_stream_get_device_name(self->stream);
+ if(!dev_name)
{
- pa_operation *o = pa_context_get_sink_info_by_name(
- self->context, alstr_get_cstr(self->device_name),
- ALCpulsePlayback_sinkNameCallback, self
- );
- wait_for_operation(o, self->loop);
+ pa_operation *op{pa_context_get_sink_info_by_name(self->context,
+ self->device_name.c_str(), PulsePlayback_sinkNameCallback, self
+ )};
+ wait_for_operation(op, self->loop);
}
else
{
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- alstr_copy(&device->DeviceName, dev_name);
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
+ alstr_copy_cstr(&device->DeviceName, dev_name);
}
- pa_threaded_mainloop_unlock(self->loop);
-
return ALC_NO_ERROR;
}
-static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
+static ALCboolean PulsePlayback_reset(PulsePlayback *self)
{
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- pa_stream_flags_t flags = 0;
- const char *mapname = NULL;
- pa_channel_map chanmap;
- pa_operation *o;
-
- pa_threaded_mainloop_lock(self->loop);
+ unique_palock palock{self->loop};
if(self->stream)
{
- pa_stream_set_state_callback(self->stream, NULL, NULL);
- pa_stream_set_moved_callback(self->stream, NULL, NULL);
- pa_stream_set_write_callback(self->stream, NULL, NULL);
- pa_stream_set_buffer_attr_callback(self->stream, NULL, NULL);
+ pa_stream_set_state_callback(self->stream, nullptr, nullptr);
+ pa_stream_set_moved_callback(self->stream, nullptr, nullptr);
+ pa_stream_set_write_callback(self->stream, nullptr, nullptr);
+ pa_stream_set_buffer_attr_callback(self->stream, nullptr, nullptr);
pa_stream_disconnect(self->stream);
pa_stream_unref(self->stream);
- self->stream = NULL;
+ self->stream = nullptr;
}
- o = pa_context_get_sink_info_by_name(self->context, alstr_get_cstr(self->device_name),
- ALCpulsePlayback_sinkInfoCallback, self);
- wait_for_operation(o, self->loop);
+ pa_operation *op{pa_context_get_sink_info_by_name(self->context,
+ self->device_name.c_str(), PulsePlayback_sinkInfoCallback, self
+ )};
+ wait_for_operation(op, self->loop);
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
+ pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY |
+ PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE};
+ if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", 0))
+ flags |= PA_STREAM_DONT_MOVE;
if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), "pulse", "fix-rate", 0) ||
!(device->Flags&DEVICE_FREQUENCY_REQUEST))
flags |= PA_STREAM_FIX_RATE;
- flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
- flags |= PA_STREAM_ADJUST_LATENCY;
- flags |= PA_STREAM_START_CORKED;
- if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0))
- flags |= PA_STREAM_DONT_MOVE;
switch(device->FmtType)
{
@@ -1017,10 +1048,11 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
if(pa_sample_spec_valid(&self->spec) == 0)
{
ERR("Invalid sample format\n");
- pa_threaded_mainloop_unlock(self->loop);
return ALC_FALSE;
}
+ const char *mapname{nullptr};
+ pa_channel_map chanmap;
switch(device->FmtChans)
{
case DevFmtMono:
@@ -1051,7 +1083,6 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
if(!pa_channel_map_parse(&chanmap, mapname))
{
ERR("Failed to build channel map for %s\n", DevFmtChannelsString(device->FmtChans));
- pa_threaded_mainloop_unlock(self->loop);
return ALC_FALSE;
}
SetDefaultWFXChannelOrder(device);
@@ -1062,17 +1093,14 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
self->attr.tlength = self->attr.minreq * maxu(device->NumUpdates, 2);
self->attr.maxlength = -1;
- self->stream = ALCpulsePlayback_connectStream(alstr_get_cstr(self->device_name),
+ self->stream = PulsePlayback_connectStream(self->device_name.c_str(),
self->loop, self->context, flags, &self->attr, &self->spec, &chanmap
);
if(!self->stream)
- {
- pa_threaded_mainloop_unlock(self->loop);
return ALC_FALSE;
- }
- pa_stream_set_state_callback(self->stream, ALCpulsePlayback_streamStateCallback, self);
- pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self);
- pa_stream_set_write_callback(self->stream, ALCpulsePlayback_streamWriteCallback, self);
+ pa_stream_set_state_callback(self->stream, PulsePlayback_streamStateCallback, self);
+ pa_stream_set_moved_callback(self->stream, PulsePlayback_streamMovedCallback, self);
+ pa_stream_set_write_callback(self->stream, PulsePlayback_streamWriteCallback, self);
self->spec = *(pa_stream_get_sample_spec(self->stream));
if(device->Frequency != self->spec.rate)
@@ -1088,15 +1116,15 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
self->attr.maxlength = -1;
self->attr.prebuf = 0;
- o = pa_stream_set_buffer_attr(self->stream, &self->attr,
- stream_success_callback, self->loop);
- wait_for_operation(o, self->loop);
+ op = pa_stream_set_buffer_attr(self->stream, &self->attr,
+ stream_success_callback, self->loop);
+ wait_for_operation(op, self->loop);
device->Frequency = self->spec.rate;
}
- pa_stream_set_buffer_attr_callback(self->stream, ALCpulsePlayback_bufferAttrCallback, self);
- ALCpulsePlayback_bufferAttrCallback(self->stream, self);
+ pa_stream_set_buffer_attr_callback(self->stream, PulsePlayback_bufferAttrCallback, self);
+ PulsePlayback_bufferAttrCallback(self->stream, self);
device->NumUpdates = (ALuint)clampu64(
(self->attr.tlength + self->attr.minreq/2) / self->attr.minreq, 2, 16
@@ -1111,7 +1139,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
*/
if(self->attr.prebuf != 0)
{
- ALuint len = self->attr.prebuf / pa_frame_size(&self->spec);
+ ALuint len{self->attr.prebuf / (ALuint)pa_frame_size(&self->spec)};
if(len <= device->UpdateSize*device->NumUpdates)
ERR("Non-0 prebuf, %u samples (%u bytes), device has %u samples\n",
len, self->attr.prebuf, device->UpdateSize*device->NumUpdates);
@@ -1123,24 +1151,29 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
}
}
- pa_threaded_mainloop_unlock(self->loop);
return ALC_TRUE;
}
-static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self)
+static ALCboolean PulsePlayback_start(PulsePlayback *self)
{
- ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
- if(althrd_create(&self->thread, ALCpulsePlayback_mixerProc, self) != althrd_success)
- return ALC_FALSE;
- return ALC_TRUE;
+ try {
+ self->killNow.store(AL_FALSE, std::memory_order_release);
+ self->thread = std::thread(PulsePlayback_mixerProc, self);
+ return ALC_TRUE;
+ }
+ catch(std::exception& e) {
+ ERR("Failed to start thread: %s\n", e.what());
+ }
+ catch(...) {
+ ERR("Failed to start thread\n");
+ }
+ return ALC_FALSE;
}
-static void ALCpulsePlayback_stop(ALCpulsePlayback *self)
+static void PulsePlayback_stop(PulsePlayback *self)
{
- pa_operation *o;
- int res;
-
- if(!self->stream || ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
+ self->killNow.store(AL_TRUE, std::memory_order_release);
+ if(!self->stream || !self->thread.joinable())
return;
/* Signal the main loop in case PulseAudio isn't sending us audio requests
@@ -1148,30 +1181,29 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self)
* the mixer is between checking the killNow flag but before waiting for
* the signal.
*/
- pa_threaded_mainloop_lock(self->loop);
- pa_threaded_mainloop_unlock(self->loop);
- pa_threaded_mainloop_signal(self->loop, 0);
- althrd_join(self->thread, &res);
+ unique_palock palock{self->loop};
+ palock.unlock();
- pa_threaded_mainloop_lock(self->loop);
+ pa_threaded_mainloop_signal(self->loop, 0);
+ self->thread.join();
- o = pa_stream_cork(self->stream, 1, stream_success_callback, self->loop);
- wait_for_operation(o, self->loop);
+ palock.lock();
- pa_threaded_mainloop_unlock(self->loop);
+ pa_operation *op{pa_stream_cork(self->stream, 1, stream_success_callback, self->loop)};
+ wait_for_operation(op, self->loop);
}
-static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self)
+static ClockLatency PulsePlayback_getClockLatency(PulsePlayback *self)
{
ClockLatency ret;
pa_usec_t latency;
int neg, err;
- pa_threaded_mainloop_lock(self->loop);
- ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice);
- err = pa_stream_get_latency(self->stream, &latency, &neg);
- pa_threaded_mainloop_unlock(self->loop);
+ { palock_guard _{self->loop};
+ ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice);
+ err = pa_stream_get_latency(self->stream, &latency, &neg);
+ }
if(UNLIKELY(err != 0))
{
@@ -1192,94 +1224,87 @@ static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self)
}
-static void ALCpulsePlayback_lock(ALCpulsePlayback *self)
+static void PulsePlayback_lock(PulsePlayback *self)
{
pa_threaded_mainloop_lock(self->loop);
}
-static void ALCpulsePlayback_unlock(ALCpulsePlayback *self)
+static void PulsePlayback_unlock(PulsePlayback *self)
{
pa_threaded_mainloop_unlock(self->loop);
}
-typedef struct ALCpulseCapture {
- DERIVE_FROM_TYPE(ALCbackend);
-
- al_string device_name;
+struct PulseCapture final : public ALCbackend {
+ std::string device_name;
- const void *cap_store;
- size_t cap_len;
- size_t cap_remain;
+ const void *cap_store{nullptr};
+ size_t cap_len{0};
+ size_t cap_remain{0};
- ALCuint last_readable;
+ ALCuint last_readable{0};
pa_buffer_attr attr;
pa_sample_spec spec;
- pa_threaded_mainloop *loop;
-
- pa_stream *stream;
- pa_context *context;
-} ALCpulseCapture;
-
-static void ALCpulseCapture_deviceCallback(pa_context *context, const pa_source_info *info, int eol, void *pdata);
-static void ALCpulseCapture_probeDevices(void);
-
-static void ALCpulseCapture_contextStateCallback(pa_context *context, void *pdata);
-static void ALCpulseCapture_streamStateCallback(pa_stream *stream, void *pdata);
-static void ALCpulseCapture_sourceNameCallback(pa_context *context, const pa_source_info *info, int eol, void *pdata);
-static void ALCpulseCapture_streamMovedCallback(pa_stream *stream, void *pdata);
-static pa_stream *ALCpulseCapture_connectStream(const char *device_name,
- pa_threaded_mainloop *loop, pa_context *context,
- pa_stream_flags_t flags, pa_buffer_attr *attr,
- pa_sample_spec *spec, pa_channel_map *chanmap);
-
-static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device);
-static void ALCpulseCapture_Destruct(ALCpulseCapture *self);
-static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name);
-static DECLARE_FORWARD(ALCpulseCapture, ALCbackend, ALCboolean, reset)
-static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self);
-static void ALCpulseCapture_stop(ALCpulseCapture *self);
-static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *buffer, ALCuint samples);
-static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self);
-static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self);
-static void ALCpulseCapture_lock(ALCpulseCapture *self);
-static void ALCpulseCapture_unlock(ALCpulseCapture *self);
-DECLARE_DEFAULT_ALLOCATORS(ALCpulseCapture)
-
-DEFINE_ALCBACKEND_VTABLE(ALCpulseCapture);
-
-
-static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device)
+ pa_threaded_mainloop *loop{nullptr};
+
+ pa_stream *stream{nullptr};
+ pa_context *context{nullptr};
+};
+
+static void PulseCapture_deviceCallback(pa_context *context, const pa_source_info *info, int eol, void *pdata);
+static void PulseCapture_probeDevices(void);
+
+static void PulseCapture_contextStateCallback(pa_context *context, void *pdata);
+static void PulseCapture_streamStateCallback(pa_stream *stream, void *pdata);
+static void PulseCapture_sourceNameCallback(pa_context *context, const pa_source_info *info, int eol, void *pdata);
+static void PulseCapture_streamMovedCallback(pa_stream *stream, void *pdata);
+static pa_stream *PulseCapture_connectStream(const char *device_name,
+ pa_threaded_mainloop *loop, pa_context *context,
+ pa_stream_flags_t flags, pa_buffer_attr *attr,
+ pa_sample_spec *spec, pa_channel_map *chanmap);
+
+static void PulseCapture_Construct(PulseCapture *self, ALCdevice *device);
+static void PulseCapture_Destruct(PulseCapture *self);
+static ALCenum PulseCapture_open(PulseCapture *self, const ALCchar *name);
+static DECLARE_FORWARD(PulseCapture, ALCbackend, ALCboolean, reset)
+static ALCboolean PulseCapture_start(PulseCapture *self);
+static void PulseCapture_stop(PulseCapture *self);
+static ALCenum PulseCapture_captureSamples(PulseCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALCuint PulseCapture_availableSamples(PulseCapture *self);
+static ClockLatency PulseCapture_getClockLatency(PulseCapture *self);
+static void PulseCapture_lock(PulseCapture *self);
+static void PulseCapture_unlock(PulseCapture *self);
+DECLARE_DEFAULT_ALLOCATORS(PulseCapture)
+
+DEFINE_ALCBACKEND_VTABLE(PulseCapture);
+
+
+static void PulseCapture_Construct(PulseCapture *self, ALCdevice *device)
{
+ new (self) PulseCapture();
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
- SET_VTABLE2(ALCpulseCapture, ALCbackend, self);
-
- self->loop = NULL;
- AL_STRING_INIT(self->device_name);
+ SET_VTABLE2(PulseCapture, ALCbackend, self);
}
-static void ALCpulseCapture_Destruct(ALCpulseCapture *self)
+static void PulseCapture_Destruct(PulseCapture *self)
{
if(self->loop)
{
pulse_close(self->loop, self->context, self->stream);
- self->loop = NULL;
- self->context = NULL;
- self->stream = NULL;
+ self->loop = nullptr;
+ self->context = nullptr;
+ self->stream = nullptr;
}
- AL_STRING_DEINIT(self->device_name);
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+ self->~PulseCapture();
}
-static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa_source_info *info, int eol, void *pdata)
+static void PulseCapture_deviceCallback(pa_context *UNUSED(context), const pa_source_info *info, int eol, void *pdata)
{
- pa_threaded_mainloop *loop = pdata;
- const DevMap *iter;
- DevMap entry;
- int count;
+ auto loop = reinterpret_cast<pa_threaded_mainloop*>(pdata);
if(eol)
{
@@ -1287,86 +1312,74 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa
return;
}
-#define MATCH_INFO_NAME(iter) (alstr_cmp_cstr((iter)->device_name, info->name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_INFO_NAME);
- if(iter != VECTOR_END(CaptureDevices)) return;
-#undef MATCH_INFO_NAME
-
- AL_STRING_INIT(entry.name);
- AL_STRING_INIT(entry.device_name);
-
- alstr_copy_cstr(&entry.device_name, info->name);
+ /* Skip this device is if it's already in the list. */
+ if(std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
+ [info](const DevMap &entry) -> bool
+ { return entry.device_name == info->name; }
+ ) != CaptureDevices.cend())
+ return;
- count = 0;
- while(1)
+ /* Make sure the display name (description) is unique. Append a number
+ * counter as needed.
+ */
+ int count{1};
+ std::string newname{info->description};
+ while(checkName(CaptureDevices, newname))
{
- alstr_copy_cstr(&entry.name, info->description);
- if(count != 0)
- {
- char str[64];
- snprintf(str, sizeof(str), " #%d", count+1);
- alstr_append_cstr(&entry.name, str);
- }
-
-#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_ENTRY);
- if(iter == VECTOR_END(CaptureDevices)) break;
-#undef MATCH_ENTRY
- count++;
+ newname = info->description;
+ newname += " #";
+ newname += std::to_string(++count);
}
+ CaptureDevices.emplace_back(std::move(newname), info->name);
+ DevMap &newentry = CaptureDevices.back();
- TRACE("Got device \"%s\", \"%s\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.device_name));
-
- VECTOR_PUSH_BACK(CaptureDevices, entry);
+ TRACE("Got device \"%s\", \"%s\"\n", newentry.name.c_str(), newentry.device_name.c_str());
}
-static void ALCpulseCapture_probeDevices(void)
+static void PulseCapture_probeDevices(void)
{
- pa_threaded_mainloop *loop;
+ CaptureDevices.clear();
- clear_devlist(&CaptureDevices);
-
- if((loop=pa_threaded_mainloop_new()) &&
- pa_threaded_mainloop_start(loop) >= 0)
+ pa_threaded_mainloop *loop{pa_threaded_mainloop_new()};
+ if(loop && pa_threaded_mainloop_start(loop) >= 0)
{
- pa_context *context;
+ unique_palock palock{loop};
- pa_threaded_mainloop_lock(loop);
- context = connect_context(loop, AL_FALSE);
+ pa_context *context{connect_context(loop, AL_FALSE)};
if(context)
{
- pa_operation *o;
- pa_stream_flags_t flags;
- pa_sample_spec spec;
- pa_stream *stream;
-
- flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
- PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE;
+ pa_stream_flags_t flags{PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
+ PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE};
+ pa_sample_spec spec;
spec.format = PA_SAMPLE_S16NE;
spec.rate = 44100;
spec.channels = 1;
- stream = ALCpulseCapture_connectStream(NULL, loop, context, flags,
- NULL, &spec, NULL);
+ pa_stream *stream{PulseCapture_connectStream(nullptr,
+ loop, context, flags, nullptr, &spec, nullptr
+ )};
if(stream)
{
- o = pa_context_get_source_info_by_name(context, pa_stream_get_device_name(stream),
- ALCpulseCapture_deviceCallback, loop);
- wait_for_operation(o, loop);
+ pa_operation *op{pa_context_get_source_info_by_name(context,
+ pa_stream_get_device_name(stream), PulseCapture_deviceCallback, loop
+ )};
+ wait_for_operation(op, loop);
pa_stream_disconnect(stream);
pa_stream_unref(stream);
- stream = NULL;
+ stream = nullptr;
}
- o = pa_context_get_source_info_list(context, ALCpulseCapture_deviceCallback, loop);
- wait_for_operation(o, loop);
+ pa_operation *op{pa_context_get_source_info_list(context,
+ PulseCapture_deviceCallback, loop
+ )};
+ wait_for_operation(op, loop);
pa_context_disconnect(context);
pa_context_unref(context);
}
- pa_threaded_mainloop_unlock(loop);
+ palock.unlock();
pa_threaded_mainloop_stop(loop);
}
if(loop)
@@ -1374,9 +1387,9 @@ static void ALCpulseCapture_probeDevices(void)
}
-static void ALCpulseCapture_contextStateCallback(pa_context *context, void *pdata)
+static void PulseCapture_contextStateCallback(pa_context *context, void *pdata)
{
- ALCpulseCapture *self = pdata;
+ auto self = reinterpret_cast<PulseCapture*>(pdata);
if(pa_context_get_state(context) == PA_CONTEXT_FAILED)
{
ERR("Received context failure!\n");
@@ -1385,9 +1398,9 @@ static void ALCpulseCapture_contextStateCallback(pa_context *context, void *pdat
pa_threaded_mainloop_signal(self->loop, 0);
}
-static void ALCpulseCapture_streamStateCallback(pa_stream *stream, void *pdata)
+static void PulseCapture_streamStateCallback(pa_stream *stream, void *pdata)
{
- ALCpulseCapture *self = pdata;
+ auto self = reinterpret_cast<PulseCapture*>(pdata);
if(pa_stream_get_state(stream) == PA_STREAM_FAILED)
{
ERR("Received stream failure!\n");
@@ -1397,10 +1410,9 @@ static void ALCpulseCapture_streamStateCallback(pa_stream *stream, void *pdata)
}
-static void ALCpulseCapture_sourceNameCallback(pa_context *UNUSED(context), const pa_source_info *info, int eol, void *pdata)
+static void PulseCapture_sourceNameCallback(pa_context *UNUSED(context), const pa_source_info *info, int eol, void *pdata)
{
- ALCpulseCapture *self = pdata;
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+ auto self = reinterpret_cast<PulseCapture*>(pdata);
if(eol)
{
@@ -1408,33 +1420,33 @@ static void ALCpulseCapture_sourceNameCallback(pa_context *UNUSED(context), cons
return;
}
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
alstr_copy_cstr(&device->DeviceName, info->description);
}
-static void ALCpulseCapture_streamMovedCallback(pa_stream *stream, void *pdata)
+static void PulseCapture_streamMovedCallback(pa_stream *stream, void *pdata)
{
- ALCpulseCapture *self = pdata;
+ auto self = reinterpret_cast<PulseCapture*>(pdata);
- alstr_copy_cstr(&self->device_name, pa_stream_get_device_name(stream));
+ self->device_name = pa_stream_get_device_name(stream);
- TRACE("Stream moved to %s\n", alstr_get_cstr(self->device_name));
+ TRACE("Stream moved to %s\n", self->device_name.c_str());
}
-static pa_stream *ALCpulseCapture_connectStream(const char *device_name,
+static pa_stream *PulseCapture_connectStream(const char *device_name,
pa_threaded_mainloop *loop, pa_context *context,
pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec,
pa_channel_map *chanmap)
{
- pa_stream_state_t state;
- pa_stream *stream;
-
- stream = pa_stream_new_with_proplist(context, "Capture Stream", spec, chanmap, prop_filter);
+ pa_stream *stream{pa_stream_new_with_proplist(context,
+ "Capture Stream", spec, chanmap, prop_filter
+ )};
if(!stream)
{
ERR("pa_stream_new_with_proplist() failed: %s\n", pa_strerror(pa_context_errno(context)));
- return NULL;
+ return nullptr;
}
pa_stream_set_state_callback(stream, stream_state_callback, loop);
@@ -1443,55 +1455,51 @@ static pa_stream *ALCpulseCapture_connectStream(const char *device_name,
{
ERR("Stream did not connect: %s\n", pa_strerror(pa_context_errno(context)));
pa_stream_unref(stream);
- return NULL;
+ return nullptr;
}
+ pa_stream_state_t state;
while((state=pa_stream_get_state(stream)) != PA_STREAM_READY)
{
if(!PA_STREAM_IS_GOOD(state))
{
ERR("Stream did not get ready: %s\n", pa_strerror(pa_context_errno(context)));
pa_stream_unref(stream);
- return NULL;
+ return nullptr;
}
pa_threaded_mainloop_wait(loop);
}
- pa_stream_set_state_callback(stream, NULL, NULL);
+ pa_stream_set_state_callback(stream, nullptr, nullptr);
return stream;
}
-static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
+static ALCenum PulseCapture_open(PulseCapture *self, const ALCchar *name)
{
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- const char *pulse_name = NULL;
- pa_stream_flags_t flags = 0;
- const char *mapname = NULL;
- pa_channel_map chanmap;
- ALuint samples;
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
+ const char *pulse_name{nullptr};
if(name)
{
- const DevMap *iter;
-
- if(VECTOR_SIZE(CaptureDevices) == 0)
- ALCpulseCapture_probeDevices();
+ if(CaptureDevices.empty())
+ PulseCapture_probeDevices();
-#define MATCH_NAME(iter) (alstr_cmp_cstr((iter)->name, name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
-#undef MATCH_NAME
- if(iter == VECTOR_END(CaptureDevices))
+ auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
+ [name](const DevMap &entry) -> bool
+ { return entry.name == name; }
+ );
+ if(iter == CaptureDevices.cend())
return ALC_INVALID_VALUE;
- pulse_name = alstr_get_cstr(iter->device_name);
- alstr_copy(&device->DeviceName, iter->name);
+ pulse_name = iter->device_name.c_str();
+ alstr_copy_cstr(&device->DeviceName, iter->name.c_str());
}
- if(!pulse_open(&self->loop, &self->context, ALCpulseCapture_contextStateCallback, self))
- return ALC_INVALID_VALUE;
+ std::tie(self->loop, self->context) = pulse_open(PulseCapture_contextStateCallback, self);
+ if(!self->loop) return ALC_INVALID_VALUE;
- pa_threaded_mainloop_lock(self->loop);
+ unique_palock palock{self->loop};
switch(device->FmtType)
{
@@ -1511,10 +1519,11 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
case DevFmtUShort:
case DevFmtUInt:
ERR("%s capture samples not supported\n", DevFmtTypeString(device->FmtType));
- pa_threaded_mainloop_unlock(self->loop);
- goto fail;
+ return ALC_INVALID_VALUE;
}
+ const char *mapname{nullptr};
+ pa_channel_map chanmap;
switch(device->FmtChans)
{
case DevFmtMono:
@@ -1540,14 +1549,12 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
break;
case DevFmtAmbi3D:
ERR("%s capture samples not supported\n", DevFmtChannelsString(device->FmtChans));
- pa_threaded_mainloop_unlock(self->loop);
- goto fail;
+ return ALC_INVALID_VALUE;
}
if(!pa_channel_map_parse(&chanmap, mapname))
{
ERR("Failed to build channel map for %s\n", DevFmtChannelsString(device->FmtChans));
- pa_threaded_mainloop_unlock(self->loop);
- return ALC_FALSE;
+ return ALC_INVALID_VALUE;
}
self->spec.rate = device->Frequency;
@@ -1556,18 +1563,16 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
if(pa_sample_spec_valid(&self->spec) == 0)
{
ERR("Invalid sample format\n");
- pa_threaded_mainloop_unlock(self->loop);
- goto fail;
+ return ALC_INVALID_VALUE;
}
if(!pa_channel_map_init_auto(&chanmap, self->spec.channels, PA_CHANNEL_MAP_WAVEEX))
{
ERR("Couldn't build map for channel count (%d)!\n", self->spec.channels);
- pa_threaded_mainloop_unlock(self->loop);
- goto fail;
+ return ALC_INVALID_VALUE;
}
- samples = device->UpdateSize * device->NumUpdates;
+ ALuint samples{device->UpdateSize * device->NumUpdates};
samples = maxu(samples, 100 * device->Frequency / 1000);
self->attr.minreq = -1;
@@ -1577,85 +1582,66 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
self->attr.fragsize = minu(samples, 50*device->Frequency/1000) *
pa_frame_size(&self->spec);
- flags |= PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY;
- if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0))
+ pa_stream_flags_t flags{PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY};
+ if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", 0))
flags |= PA_STREAM_DONT_MOVE;
TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)");
- self->stream = ALCpulseCapture_connectStream(pulse_name,
+ self->stream = PulseCapture_connectStream(pulse_name,
self->loop, self->context, flags, &self->attr, &self->spec, &chanmap
);
if(!self->stream)
- {
- pa_threaded_mainloop_unlock(self->loop);
- goto fail;
- }
- pa_stream_set_moved_callback(self->stream, ALCpulseCapture_streamMovedCallback, self);
- pa_stream_set_state_callback(self->stream, ALCpulseCapture_streamStateCallback, self);
+ return ALC_INVALID_VALUE;
+ pa_stream_set_moved_callback(self->stream, PulseCapture_streamMovedCallback, self);
+ pa_stream_set_state_callback(self->stream, PulseCapture_streamStateCallback, self);
- alstr_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream));
+ self->device_name = pa_stream_get_device_name(self->stream);
if(alstr_empty(device->DeviceName))
{
- pa_operation *o = pa_context_get_source_info_by_name(
- self->context, alstr_get_cstr(self->device_name),
- ALCpulseCapture_sourceNameCallback, self
- );
- wait_for_operation(o, self->loop);
+ pa_operation *op{pa_context_get_source_info_by_name(self->context,
+ self->device_name.c_str(), PulseCapture_sourceNameCallback, self
+ )};
+ wait_for_operation(op, self->loop);
}
- pa_threaded_mainloop_unlock(self->loop);
return ALC_NO_ERROR;
-
-fail:
- pulse_close(self->loop, self->context, self->stream);
- self->loop = NULL;
- self->context = NULL;
- self->stream = NULL;
-
- return ALC_INVALID_VALUE;
}
-static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self)
+static ALCboolean PulseCapture_start(PulseCapture *self)
{
- pa_operation *o;
- pa_threaded_mainloop_lock(self->loop);
- o = pa_stream_cork(self->stream, 0, stream_success_callback, self->loop);
- wait_for_operation(o, self->loop);
- pa_threaded_mainloop_unlock(self->loop);
+ palock_guard _{self->loop};
+ pa_operation *op{pa_stream_cork(self->stream, 0, stream_success_callback, self->loop)};
+ wait_for_operation(op, self->loop);
return ALC_TRUE;
}
-static void ALCpulseCapture_stop(ALCpulseCapture *self)
+static void PulseCapture_stop(PulseCapture *self)
{
- pa_operation *o;
- pa_threaded_mainloop_lock(self->loop);
- o = pa_stream_cork(self->stream, 1, stream_success_callback, self->loop);
- wait_for_operation(o, self->loop);
- pa_threaded_mainloop_unlock(self->loop);
+ palock_guard _{self->loop};
+ pa_operation *op{pa_stream_cork(self->stream, 1, stream_success_callback, self->loop)};
+ wait_for_operation(op, self->loop);
}
-static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *buffer, ALCuint samples)
+static ALCenum PulseCapture_captureSamples(PulseCapture *self, ALCvoid *buffer, ALCuint samples)
{
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- ALCuint todo = samples * pa_frame_size(&self->spec);
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
+ ALCuint todo{samples * static_cast<ALCuint>(pa_frame_size(&self->spec))};
/* Capture is done in fragment-sized chunks, so we loop until we get all
* that's available */
self->last_readable -= todo;
- pa_threaded_mainloop_lock(self->loop);
+ unique_palock palock{self->loop};
while(todo > 0)
{
- size_t rem = todo;
+ size_t rem{todo};
if(self->cap_len == 0)
{
- pa_stream_state_t state;
-
- state = pa_stream_get_state(self->stream);
+ pa_stream_state_t state{pa_stream_get_state(self->stream)};
if(!PA_STREAM_IS_GOOD(state))
{
aluHandleDisconnect(device, "Bad capture state: %u", state);
- break;
+ return ALC_INVALID_DEVICE;
}
if(pa_stream_peek(self->stream, &self->cap_store, &self->cap_len) < 0)
{
@@ -1663,7 +1649,7 @@ static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *bu
pa_strerror(pa_context_errno(self->context)));
aluHandleDisconnect(device, "Failed retrieving capture samples: %s",
pa_strerror(pa_context_errno(self->context)));
- break;
+ return ALC_INVALID_DEVICE;
}
self->cap_remain = self->cap_len;
}
@@ -1683,31 +1669,29 @@ static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *bu
self->cap_len = 0;
}
}
- pa_threaded_mainloop_unlock(self->loop);
+ palock.unlock();
if(todo > 0)
memset(buffer, ((device->FmtType==DevFmtUByte) ? 0x80 : 0), todo);
return ALC_NO_ERROR;
}
-static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self)
+static ALCuint PulseCapture_availableSamples(PulseCapture *self)
{
- ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- size_t readable = self->cap_remain;
+ ALCdevice *device{STATIC_CAST(ALCbackend,self)->mDevice};
+ size_t readable{self->cap_remain};
if(ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
{
- ssize_t got;
- pa_threaded_mainloop_lock(self->loop);
- got = pa_stream_readable_size(self->stream);
- if(got < 0)
+ palock_guard _{self->loop};
+ size_t got{pa_stream_readable_size(self->stream)};
+ if(static_cast<ssize_t>(got) < 0)
{
ERR("pa_stream_readable_size() failed: %s\n", pa_strerror(got));
aluHandleDisconnect(device, "Failed getting readable size: %s", pa_strerror(got));
}
- else if((size_t)got > self->cap_len)
+ else if(got > self->cap_len)
readable += got - self->cap_len;
- pa_threaded_mainloop_unlock(self->loop);
}
if(self->last_readable < readable)
@@ -1716,16 +1700,16 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self)
}
-static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self)
+static ClockLatency PulseCapture_getClockLatency(PulseCapture *self)
{
ClockLatency ret;
pa_usec_t latency;
int neg, err;
- pa_threaded_mainloop_lock(self->loop);
- ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice);
- err = pa_stream_get_latency(self->stream, &latency, &neg);
- pa_threaded_mainloop_unlock(self->loop);
+ { palock_guard _{self->loop};
+ ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice);
+ err = pa_stream_get_latency(self->stream, &latency, &neg);
+ }
if(UNLIKELY(err != 0))
{
@@ -1741,52 +1725,50 @@ static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self)
}
-static void ALCpulseCapture_lock(ALCpulseCapture *self)
+static void PulseCapture_lock(PulseCapture *self)
{
pa_threaded_mainloop_lock(self->loop);
}
-static void ALCpulseCapture_unlock(ALCpulseCapture *self)
+static void PulseCapture_unlock(PulseCapture *self)
{
pa_threaded_mainloop_unlock(self->loop);
}
-typedef struct ALCpulseBackendFactory {
- DERIVE_FROM_TYPE(ALCbackendFactory);
-} ALCpulseBackendFactory;
-#define ALCPULSEBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCpulseBackendFactory, ALCbackendFactory) } }
-
-static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory *self);
-static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory *self);
-static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory *self, ALCbackend_Type type);
-static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory *self, enum DevProbe type, al_string *outnames);
-static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
-DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory);
+struct PulseBackendFactory final : public ALCbackendFactory {
+ PulseBackendFactory() noexcept;
+};
+#define ALCPULSEBACKENDFACTORY_INITIALIZER GET_VTABLE2(PulseBackendFactory, ALCbackendFactory)
+static ALCboolean PulseBackendFactory_init(PulseBackendFactory *self);
+static void PulseBackendFactory_deinit(PulseBackendFactory *self);
+static ALCboolean PulseBackendFactory_querySupport(PulseBackendFactory *self, ALCbackend_Type type);
+static void PulseBackendFactory_probe(PulseBackendFactory *self, enum DevProbe type, al_string *outnames);
+static ALCbackend* PulseBackendFactory_createBackend(PulseBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(PulseBackendFactory);
-static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(self))
+PulseBackendFactory::PulseBackendFactory() noexcept
+ : ALCbackendFactory{ALCPULSEBACKENDFACTORY_INITIALIZER}
{
- ALCboolean ret = ALC_FALSE;
+}
+
- VECTOR_INIT(PlaybackDevices);
- VECTOR_INIT(CaptureDevices);
+static ALCboolean PulseBackendFactory_init(PulseBackendFactory* UNUSED(self))
+{
+ ALCboolean ret{ALC_FALSE};
if(pulse_load())
{
- pa_threaded_mainloop *loop;
-
- pulse_ctx_flags = 0;
- if(!GetConfigValueBool(NULL, "pulse", "spawn-server", 1))
+ pulse_ctx_flags = PA_CONTEXT_NOFLAGS;
+ if(!GetConfigValueBool(nullptr, "pulse", "spawn-server", 1))
pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN;
- if((loop=pa_threaded_mainloop_new()) &&
- pa_threaded_mainloop_start(loop) >= 0)
+ pa_threaded_mainloop *loop{pa_threaded_mainloop_new()};
+ if(loop && pa_threaded_mainloop_start(loop) >= 0)
{
- pa_context *context;
-
- pa_threaded_mainloop_lock(loop);
- context = connect_context(loop, AL_TRUE);
+ unique_palock palock{loop};
+ pa_context *context{connect_context(loop, AL_TRUE)};
if(context)
{
ret = ALC_TRUE;
@@ -1796,13 +1778,13 @@ static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(sel
* the process to inherit them. This attempts to filter those
* properties out by setting them to 0-length data. */
prop_filter = pa_proplist_new();
- pa_proplist_set(prop_filter, PA_PROP_MEDIA_ROLE, NULL, 0);
- pa_proplist_set(prop_filter, "phonon.streamid", NULL, 0);
+ pa_proplist_set(prop_filter, PA_PROP_MEDIA_ROLE, nullptr, 0);
+ pa_proplist_set(prop_filter, "phonon.streamid", nullptr, 0);
pa_context_disconnect(context);
pa_context_unref(context);
}
- pa_threaded_mainloop_unlock(loop);
+ palock.unlock();
pa_threaded_mainloop_stop(loop);
}
if(loop)
@@ -1812,68 +1794,68 @@ static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(sel
return ret;
}
-static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory* UNUSED(self))
+static void PulseBackendFactory_deinit(PulseBackendFactory* UNUSED(self))
{
- clear_devlist(&PlaybackDevices);
- VECTOR_DEINIT(PlaybackDevices);
-
- clear_devlist(&CaptureDevices);
- VECTOR_DEINIT(CaptureDevices);
+ PlaybackDevices.clear();
+ CaptureDevices.clear();
if(prop_filter)
pa_proplist_free(prop_filter);
- prop_filter = NULL;
+ prop_filter = nullptr;
/* PulseAudio doesn't like being CloseLib'd sometimes */
}
-static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UNUSED(self), ALCbackend_Type type)
+static ALCboolean PulseBackendFactory_querySupport(PulseBackendFactory* UNUSED(self), ALCbackend_Type type)
{
if(type == ALCbackend_Playback || type == ALCbackend_Capture)
return ALC_TRUE;
return ALC_FALSE;
}
-static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
+static void PulseBackendFactory_probe(PulseBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
{
+ auto add_device = [outnames](const DevMap &entry) -> void
+ {
+ const char *name{entry.name.c_str()};
+ size_t namelen{entry.name.length()};
+ /* +1 to also append the null char (to ensure a null-separated list
+ * and double-null terminated list).
+ */
+ alstr_append_range(outnames, name, name + namelen+1);
+ };
switch(type)
{
-#define APPEND_OUTNAME(e) do { \
- if(!alstr_empty((e)->name)) \
- alstr_append_range(outnames, VECTOR_BEGIN((e)->name), \
- VECTOR_END((e)->name)+1); \
-} while(0)
case ALL_DEVICE_PROBE:
- ALCpulsePlayback_probeDevices();
- VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_OUTNAME);
+ PulsePlayback_probeDevices();
+ std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device);
break;
case CAPTURE_DEVICE_PROBE:
- ALCpulseCapture_probeDevices();
- VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_OUTNAME);
+ PulseCapture_probeDevices();
+ std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device);
break;
-#undef APPEND_OUTNAME
}
}
-static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+static ALCbackend* PulseBackendFactory_createBackend(PulseBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
{
if(type == ALCbackend_Playback)
{
- ALCpulsePlayback *backend;
- NEW_OBJ(backend, ALCpulsePlayback)(device);
- if(!backend) return NULL;
+ PulsePlayback *backend;
+ NEW_OBJ(backend, PulsePlayback)(device);
+ if(!backend) return nullptr;
return STATIC_CAST(ALCbackend, backend);
}
if(type == ALCbackend_Capture)
{
- ALCpulseCapture *backend;
- NEW_OBJ(backend, ALCpulseCapture)(device);
- if(!backend) return NULL;
+ PulseCapture *backend;
+ NEW_OBJ(backend, PulseCapture)(device);
+ if(!backend) return nullptr;
return STATIC_CAST(ALCbackend, backend);
}
- return NULL;
+ return nullptr;
}
@@ -1881,40 +1863,44 @@ static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory*
#warning "Unsupported API version, backend will be unavailable!"
-typedef struct ALCpulseBackendFactory {
- DERIVE_FROM_TYPE(ALCbackendFactory);
-} ALCpulseBackendFactory;
-#define ALCPULSEBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCpulseBackendFactory, ALCbackendFactory) } }
+struct PulseBackendFactory final : public ALCbackendFactory {
+ PulseBackendFactory() noexcept;
+};
+#define ALCPULSEBACKENDFACTORY_INITIALIZER GET_VTABLE2(PulseBackendFactory, ALCbackendFactory)
-static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(self))
+static ALCboolean PulseBackendFactory_init(PulseBackendFactory* UNUSED(self))
{
return ALC_FALSE;
}
-static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory* UNUSED(self))
+static void PulseBackendFactory_deinit(PulseBackendFactory* UNUSED(self))
{
}
-static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UNUSED(self), ALCbackend_Type UNUSED(type))
+static ALCboolean PulseBackendFactory_querySupport(PulseBackendFactory* UNUSED(self), ALCbackend_Type UNUSED(type))
{
return ALC_FALSE;
}
-static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe UNUSED(type), al_string* UNUSED(outnames))
+static void PulseBackendFactory_probe(PulseBackendFactory* UNUSED(self), enum DevProbe UNUSED(type), al_string* UNUSED(outnames))
{
}
-static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory* UNUSED(self), ALCdevice* UNUSED(device), ALCbackend_Type UNUSED(type))
+static ALCbackend* PulseBackendFactory_createBackend(PulseBackendFactory* UNUSED(self), ALCdevice* UNUSED(device), ALCbackend_Type UNUSED(type))
{
- return NULL;
+ return nullptr;
}
-DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory);
+DEFINE_ALCBACKENDFACTORY_VTABLE(PulseBackendFactory);
+
+PulseBackendFactory::PulseBackendFactory() noexcept
+ : ALCbackendFactory{ALCPULSEBACKENDFACTORY_INITIALIZER}
+{ }
#endif /* PA_API_VERSION == 12 */
ALCbackendFactory *ALCpulseBackendFactory_getFactory(void)
{
- static ALCpulseBackendFactory factory = ALCPULSEBACKENDFACTORY_INITIALIZER;
+ static PulseBackendFactory factory{};
return STATIC_CAST(ALCbackendFactory, &factory);
}
diff --git a/Alc/backends/wasapi.c b/Alc/backends/wasapi.cpp
index 971a1f72..f2adf328 100644
--- a/Alc/backends/wasapi.c
+++ b/Alc/backends/wasapi.cpp
@@ -20,7 +20,6 @@
#include "config.h"
-#define COBJMACROS
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
@@ -39,10 +38,15 @@
#include <ksmedia.h>
#endif
+#include <atomic>
+#include <thread>
+#include <vector>
+#include <string>
+#include <algorithm>
+
#include "alMain.h"
#include "alu.h"
#include "ringbuffer.h"
-#include "threads.h"
#include "compat.h"
#include "alstring.h"
#include "converter.h"
@@ -50,13 +54,24 @@
#include "backends/base.h"
+/* Some headers seem to define these as macros for __uuidof, which is annoying
+ * since some headers don't declare them at all. Hopefully the ifdef is enough
+ * to tell if they need to be declared.
+ */
+#ifndef KSDATAFORMAT_SUBTYPE_PCM
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+#endif
+#ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
+#endif
DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0);
DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23,0xe0, 0xc0,0xff,0xee,0x7f,0x0e, 4 );
+
+namespace {
+
#define MONO SPEAKER_FRONT_CENTER
#define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
#define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
@@ -72,43 +87,63 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x
/* Scales the given value using 64-bit integer math, ceiling the result. */
-static inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale)
+inline ALint64 ScaleCeil(ALint64 val, ALint64 new_scale, ALint64 old_scale)
{
return (val*new_scale + old_scale-1) / old_scale;
}
-typedef struct {
- al_string name;
- al_string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent.
- WCHAR *devid;
-} DevMap;
-TYPEDEF_VECTOR(DevMap, vector_DevMap)
+struct PropVariant {
+ PROPVARIANT mProp;
+
+public:
+ PropVariant() { PropVariantInit(&mProp); }
+ ~PropVariant() { clear(); }
+
+ void clear() { PropVariantClear(&mProp); }
-static void clear_devlist(vector_DevMap *list)
+ PROPVARIANT* get() noexcept { return &mProp; }
+
+ PROPVARIANT& operator*() noexcept { return mProp; }
+ const PROPVARIANT& operator*() const noexcept { return mProp; }
+
+ PROPVARIANT* operator->() noexcept { return &mProp; }
+ const PROPVARIANT* operator->() const noexcept { return &mProp; }
+};
+
+struct DevMap {
+ std::string name;
+ std::string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent.
+ std::wstring devid;
+
+ template<typename T0, typename T1, typename T2>
+ DevMap(T0&& name_, T1&& guid_, T2&& devid_)
+ : name{std::forward<T0>(name_)}
+ , endpoint_guid{std::forward<T1>(guid_)}
+ , devid{std::forward<T2>(devid_)}
+ { }
+};
+
+bool checkName(const std::vector<DevMap> &list, const std::string &name)
{
-#define CLEAR_DEVMAP(i) do { \
- AL_STRING_DEINIT((i)->name); \
- AL_STRING_DEINIT((i)->endpoint_guid); \
- free((i)->devid); \
- (i)->devid = NULL; \
-} while(0)
- VECTOR_FOR_EACH(DevMap, *list, CLEAR_DEVMAP);
- VECTOR_RESIZE(*list, 0, 0);
-#undef CLEAR_DEVMAP
+ return std::find_if(list.cbegin(), list.cend(),
+ [&name](const DevMap &entry) -> bool
+ { return entry.name == name; }
+ ) != list.cend();
}
-static vector_DevMap PlaybackDevices;
-static vector_DevMap CaptureDevices;
+std::vector<DevMap> PlaybackDevices;
+std::vector<DevMap> CaptureDevices;
-static HANDLE ThreadHdl;
-static DWORD ThreadID;
+HANDLE ThreadHdl;
+DWORD ThreadID;
-typedef struct {
+struct ThreadRequest {
HANDLE FinishedEvt;
HRESULT result;
-} ThreadRequest;
+};
+
#define WM_USER_First (WM_USER+0)
#define WM_USER_OpenDevice (WM_USER+0)
@@ -128,13 +163,13 @@ static const char MessageStr[WM_USER_Last+1-WM_USER][20] = {
"Enumerate Devices",
};
-static inline void ReturnMsgResponse(ThreadRequest *req, HRESULT res)
+inline void ReturnMsgResponse(ThreadRequest *req, HRESULT res)
{
req->result = res;
SetEvent(req->FinishedEvt);
}
-static HRESULT WaitForResponse(ThreadRequest *req)
+HRESULT WaitForResponse(ThreadRequest *req)
{
if(WaitForSingleObject(req->FinishedEvt, INFINITE) == WAIT_OBJECT_0)
return req->result;
@@ -143,252 +178,183 @@ static HRESULT WaitForResponse(ThreadRequest *req)
}
-static void get_device_name_and_guid(IMMDevice *device, al_string *name, al_string *guid)
+using NameGUIDPair = std::pair<std::string,std::string>;
+NameGUIDPair get_device_name_and_guid(IMMDevice *device)
{
- IPropertyStore *ps;
- PROPVARIANT pvname;
- PROPVARIANT pvguid;
- HRESULT hr;
+ std::string name{DEVNAME_HEAD};
+ std::string guid;
- alstr_copy_cstr(name, DEVNAME_HEAD);
-
- hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
+ IPropertyStore *ps;
+ HRESULT hr = device->OpenPropertyStore(STGM_READ, &ps);
if(FAILED(hr))
{
WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
- alstr_append_cstr(name, "Unknown Device Name");
- if(guid!=NULL)alstr_copy_cstr(guid, "Unknown Device GUID");
- return;
+ return { name+"Unknown Device Name", "Unknown Device GUID" };
}
- PropVariantInit(&pvname);
-
- hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname);
+ PropVariant pvprop;
+ hr = ps->GetValue(reinterpret_cast<const PROPERTYKEY&>(DEVPKEY_Device_FriendlyName), pvprop.get());
if(FAILED(hr))
{
WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr);
- alstr_append_cstr(name, "Unknown Device Name");
+ name += "Unknown Device Name";
}
- else if(pvname.vt == VT_LPWSTR)
- alstr_append_wcstr(name, pvname.pwszVal);
+ else if(pvprop->vt == VT_LPWSTR)
+ name += wstr_to_utf8(pvprop->pwszVal);
else
{
- WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt);
- alstr_append_cstr(name, "Unknown Device Name");
+ WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt);
+ name += "Unknown Device Name";
}
- PropVariantClear(&pvname);
-
- if(guid!=NULL){
- PropVariantInit(&pvguid);
-
- hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&PKEY_AudioEndpoint_GUID, &pvguid);
- if(FAILED(hr))
- {
- WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr);
- alstr_copy_cstr(guid, "Unknown Device GUID");
- }
- else if(pvguid.vt == VT_LPWSTR)
- alstr_copy_wcstr(guid, pvguid.pwszVal);
- else
- {
- WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt);
- alstr_copy_cstr(guid, "Unknown Device GUID");
- }
- PropVariantClear(&pvguid);
+ pvprop.clear();
+ hr = ps->GetValue(reinterpret_cast<const PROPERTYKEY&>(PKEY_AudioEndpoint_GUID), pvprop.get());
+ if(FAILED(hr))
+ {
+ WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr);
+ guid = "Unknown Device GUID";
}
+ else if(pvprop->vt == VT_LPWSTR)
+ guid = wstr_to_utf8(pvprop->pwszVal);
+ else
+ {
+ WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvprop->vt);
+ guid = "Unknown Device GUID";
+ }
+
+ ps->Release();
- IPropertyStore_Release(ps);
+ return {name, guid};
}
-static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfactor)
+void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfactor)
{
IPropertyStore *ps;
- PROPVARIANT pvform;
- HRESULT hr;
-
- hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
+ HRESULT hr = device->OpenPropertyStore(STGM_READ, &ps);
if(FAILED(hr))
{
WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
return;
}
- PropVariantInit(&pvform);
-
- hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_FormFactor, &pvform);
+ PropVariant pvform;
+ hr = ps->GetValue(reinterpret_cast<const PROPERTYKEY&>(PKEY_AudioEndpoint_FormFactor), pvform.get());
if(FAILED(hr))
WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr);
- else if(pvform.vt == VT_UI4)
- *formfactor = pvform.ulVal;
- else if(pvform.vt == VT_EMPTY)
+ else if(pvform->vt == VT_UI4)
+ *formfactor = static_cast<EndpointFormFactor>(pvform->ulVal);
+ else if(pvform->vt == VT_EMPTY)
*formfactor = UnknownFormFactor;
else
- WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform.vt);
+ WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform->vt);
- PropVariantClear(&pvform);
- IPropertyStore_Release(ps);
+ ps->Release();
}
-static void add_device(IMMDevice *device, const WCHAR *devid, vector_DevMap *list)
+void add_device(IMMDevice *device, const WCHAR *devid, std::vector<DevMap> &list)
{
- int count = 0;
- al_string tmpname;
- DevMap entry;
-
- AL_STRING_INIT(tmpname);
- AL_STRING_INIT(entry.name);
- AL_STRING_INIT(entry.endpoint_guid);
+ std::string basename, guidstr;
+ std::tie(basename, guidstr) = get_device_name_and_guid(device);
- entry.devid = strdupW(devid);
- get_device_name_and_guid(device, &tmpname, &entry.endpoint_guid);
-
- while(1)
+ int count{1};
+ std::string newname{basename};
+ while(checkName(PlaybackDevices, newname))
{
- const DevMap *iter;
-
- alstr_copy(&entry.name, tmpname);
- if(count != 0)
- {
- char str[64];
- snprintf(str, sizeof(str), " #%d", count+1);
- alstr_append_cstr(&entry.name, str);
- }
-
-#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0)
- VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY);
- if(iter == VECTOR_END(*list)) break;
-#undef MATCH_ENTRY
- count++;
+ newname = basename;
+ newname += " #";
+ newname += std::to_string(++count);
}
+ list.emplace_back(std::move(newname), std::move(guidstr), devid);
+ const DevMap &newentry = list.back();
- TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.endpoint_guid), entry.devid);
- VECTOR_PUSH_BACK(*list, entry);
-
- AL_STRING_DEINIT(tmpname);
+ TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(),
+ newentry.endpoint_guid.c_str(), newentry.devid.c_str());
}
-static WCHAR *get_device_id(IMMDevice *device)
+WCHAR *get_device_id(IMMDevice *device)
{
WCHAR *devid;
- HRESULT hr;
- hr = IMMDevice_GetId(device, &devid);
+ HRESULT hr = device->GetId(&devid);
if(FAILED(hr))
{
ERR("Failed to get device id: %lx\n", hr);
- return NULL;
+ return nullptr;
}
return devid;
}
-static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list)
+HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, std::vector<DevMap> &list)
{
IMMDeviceCollection *coll;
- IMMDevice *defdev = NULL;
- WCHAR *defdevid = NULL;
- HRESULT hr;
- UINT count;
- UINT i;
-
- hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll);
+ HRESULT hr = devenum->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, &coll);
if(FAILED(hr))
{
ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr);
return hr;
}
- count = 0;
- hr = IMMDeviceCollection_GetCount(coll, &count);
+ IMMDevice *defdev{nullptr};
+ WCHAR *defdevid{nullptr};
+ UINT count{0};
+ hr = coll->GetCount(&count);
if(SUCCEEDED(hr) && count > 0)
{
- clear_devlist(list);
- VECTOR_RESIZE(*list, 0, count);
+ list.clear();
+ list.reserve(count);
- hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir,
- eMultimedia, &defdev);
+ hr = devenum->GetDefaultAudioEndpoint(flowdir, eMultimedia, &defdev);
}
- if(SUCCEEDED(hr) && defdev != NULL)
+ if(SUCCEEDED(hr) && defdev != nullptr)
{
defdevid = get_device_id(defdev);
if(defdevid)
add_device(defdev, defdevid, list);
}
- for(i = 0;i < count;++i)
+ for(UINT i{0};i < count;++i)
{
IMMDevice *device;
- WCHAR *devid;
-
- hr = IMMDeviceCollection_Item(coll, i, &device);
+ hr = coll->Item(i, &device);
if(FAILED(hr)) continue;
- devid = get_device_id(device);
+ WCHAR *devid = get_device_id(device);
if(devid)
{
if(wcscmp(devid, defdevid) != 0)
add_device(device, devid, list);
CoTaskMemFree(devid);
}
- IMMDevice_Release(device);
+ device->Release();
}
- if(defdev) IMMDevice_Release(defdev);
+ if(defdev) defdev->Release();
if(defdevid) CoTaskMemFree(defdevid);
- IMMDeviceCollection_Release(coll);
+ coll->Release();
return S_OK;
}
/* Proxy interface used by the message handler. */
-struct ALCwasapiProxyVtable;
-
-typedef struct ALCwasapiProxy {
- const struct ALCwasapiProxyVtable *vtbl;
-} ALCwasapiProxy;
+struct WasapiProxy {
+ virtual HRESULT openProxy() = 0;
+ virtual void closeProxy() = 0;
-struct ALCwasapiProxyVtable {
- HRESULT (*const openProxy)(ALCwasapiProxy*);
- void (*const closeProxy)(ALCwasapiProxy*);
-
- HRESULT (*const resetProxy)(ALCwasapiProxy*);
- HRESULT (*const startProxy)(ALCwasapiProxy*);
- void (*const stopProxy)(ALCwasapiProxy*);
+ virtual HRESULT resetProxy() = 0;
+ virtual HRESULT startProxy() = 0;
+ virtual void stopProxy() = 0;
};
-#define DEFINE_ALCWASAPIPROXY_VTABLE(T) \
-DECLARE_THUNK(T, ALCwasapiProxy, HRESULT, openProxy) \
-DECLARE_THUNK(T, ALCwasapiProxy, void, closeProxy) \
-DECLARE_THUNK(T, ALCwasapiProxy, HRESULT, resetProxy) \
-DECLARE_THUNK(T, ALCwasapiProxy, HRESULT, startProxy) \
-DECLARE_THUNK(T, ALCwasapiProxy, void, stopProxy) \
- \
-static const struct ALCwasapiProxyVtable T##_ALCwasapiProxy_vtable = { \
- T##_ALCwasapiProxy_openProxy, \
- T##_ALCwasapiProxy_closeProxy, \
- T##_ALCwasapiProxy_resetProxy, \
- T##_ALCwasapiProxy_startProxy, \
- T##_ALCwasapiProxy_stopProxy, \
-}
-
-static void ALCwasapiProxy_Construct(ALCwasapiProxy* UNUSED(self)) { }
-static void ALCwasapiProxy_Destruct(ALCwasapiProxy* UNUSED(self)) { }
-
-static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
+DWORD CALLBACK WasapiProxy_messageHandler(void *ptr)
{
- ThreadRequest *req = ptr;
- IMMDeviceEnumerator *Enumerator;
- ALuint deviceCount = 0;
- ALCwasapiProxy *proxy;
- HRESULT hr, cohr;
- MSG msg;
+ auto req = reinterpret_cast<ThreadRequest*>(ptr);
TRACE("Starting message thread\n");
- cohr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ HRESULT cohr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if(FAILED(cohr))
{
WARN("Failed to initialize COM: 0x%08lx\n", cohr);
@@ -396,7 +362,8 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
return 0;
}
- hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
+ HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER,
+ IID_IMMDeviceEnumerator, &ptr);
if(FAILED(hr))
{
WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr);
@@ -404,9 +371,9 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
ReturnMsgResponse(req, hr);
return 0;
}
- Enumerator = ptr;
- IMMDeviceEnumerator_Release(Enumerator);
- Enumerator = NULL;
+ auto Enumerator = reinterpret_cast<IMMDeviceEnumerator*>(ptr);
+ Enumerator->Release();
+ Enumerator = nullptr;
CoUninitialize();
@@ -414,30 +381,34 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
* returning success, otherwise PostThreadMessage may fail if it gets
* called before GetMessage.
*/
- PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+ MSG msg;
+ PeekMessage(&msg, nullptr, WM_USER, WM_USER, PM_NOREMOVE);
TRACE("Message thread initialization complete\n");
ReturnMsgResponse(req, S_OK);
TRACE("Starting message loop\n");
- while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last))
+ ALuint deviceCount{0};
+ while(GetMessage(&msg, nullptr, WM_USER_First, WM_USER_Last))
{
TRACE("Got message \"%s\" (0x%04x, lparam=%p, wparam=%p)\n",
(msg.message >= WM_USER && msg.message <= WM_USER_Last) ?
MessageStr[msg.message-WM_USER] : "Unknown",
msg.message, (void*)msg.lParam, (void*)msg.wParam
);
+
+ WasapiProxy *proxy{nullptr};
switch(msg.message)
{
case WM_USER_OpenDevice:
- req = (ThreadRequest*)msg.wParam;
- proxy = (ALCwasapiProxy*)msg.lParam;
+ req = reinterpret_cast<ThreadRequest*>(msg.wParam);
+ proxy = reinterpret_cast<WasapiProxy*>(msg.lParam);
hr = cohr = S_OK;
if(++deviceCount == 1)
- hr = cohr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ hr = cohr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if(SUCCEEDED(hr))
- hr = V0(proxy,openProxy)();
+ hr = proxy->openProxy();
if(FAILED(hr))
{
if(--deviceCount == 0 && SUCCEEDED(cohr))
@@ -448,34 +419,34 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
continue;
case WM_USER_ResetDevice:
- req = (ThreadRequest*)msg.wParam;
- proxy = (ALCwasapiProxy*)msg.lParam;
+ req = reinterpret_cast<ThreadRequest*>(msg.wParam);
+ proxy = reinterpret_cast<WasapiProxy*>(msg.lParam);
- hr = V0(proxy,resetProxy)();
+ hr = proxy->resetProxy();
ReturnMsgResponse(req, hr);
continue;
case WM_USER_StartDevice:
- req = (ThreadRequest*)msg.wParam;
- proxy = (ALCwasapiProxy*)msg.lParam;
+ req = reinterpret_cast<ThreadRequest*>(msg.wParam);
+ proxy = reinterpret_cast<WasapiProxy*>(msg.lParam);
- hr = V0(proxy,startProxy)();
+ hr = proxy->startProxy();
ReturnMsgResponse(req, hr);
continue;
case WM_USER_StopDevice:
- req = (ThreadRequest*)msg.wParam;
- proxy = (ALCwasapiProxy*)msg.lParam;
+ req = reinterpret_cast<ThreadRequest*>(msg.wParam);
+ proxy = reinterpret_cast<WasapiProxy*>(msg.lParam);
- V0(proxy,stopProxy)();
+ proxy->stopProxy();
ReturnMsgResponse(req, S_OK);
continue;
case WM_USER_CloseDevice:
- req = (ThreadRequest*)msg.wParam;
- proxy = (ALCwasapiProxy*)msg.lParam;
+ req = reinterpret_cast<ThreadRequest*>(msg.wParam);
+ proxy = reinterpret_cast<WasapiProxy*>(msg.lParam);
- V0(proxy,closeProxy)();
+ proxy->closeProxy();
if(--deviceCount == 0)
CoUninitialize();
@@ -483,24 +454,24 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
continue;
case WM_USER_Enumerate:
- req = (ThreadRequest*)msg.wParam;
+ req = reinterpret_cast<ThreadRequest*>(msg.wParam);
hr = cohr = S_OK;
if(++deviceCount == 1)
- hr = cohr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ hr = cohr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if(SUCCEEDED(hr))
- hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
+ hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, &ptr);
if(SUCCEEDED(hr))
{
- Enumerator = ptr;
+ Enumerator = reinterpret_cast<IMMDeviceEnumerator*>(ptr);
if(msg.lParam == ALL_DEVICE_PROBE)
- hr = probe_devices(Enumerator, eRender, &PlaybackDevices);
+ hr = probe_devices(Enumerator, eRender, PlaybackDevices);
else if(msg.lParam == CAPTURE_DEVICE_PROBE)
- hr = probe_devices(Enumerator, eCapture, &CaptureDevices);
+ hr = probe_devices(Enumerator, eCapture, CaptureDevices);
- IMMDeviceEnumerator_Release(Enumerator);
- Enumerator = NULL;
+ Enumerator->Release();
+ Enumerator = nullptr;
}
if(--deviceCount == 0 && SUCCEEDED(cohr))
@@ -519,39 +490,40 @@ static DWORD CALLBACK ALCwasapiProxy_messageHandler(void *ptr)
return 0;
}
+} // namespace
-typedef struct ALCwasapiPlayback {
- DERIVE_FROM_TYPE(ALCbackend);
- DERIVE_FROM_TYPE(ALCwasapiProxy);
- WCHAR *devid;
+struct ALCwasapiPlayback final : public ALCbackend, WasapiProxy {
+ HRESULT openProxy() override;
+ void closeProxy() override;
+
+ HRESULT resetProxy() override;
+ HRESULT startProxy() override;
+ void stopProxy() override;
- IMMDevice *mmdev;
- IAudioClient *client;
- IAudioRenderClient *render;
- HANDLE NotifyEvent;
+ std::wstring mDevId;
- HANDLE MsgEvent;
+ IMMDevice *mMMDev{nullptr};
+ IAudioClient *mClient{nullptr};
+ IAudioRenderClient *mRender{nullptr};
+ HANDLE mNotifyEvent{nullptr};
- ATOMIC(UINT32) Padding;
+ HANDLE mMsgEvent{nullptr};
- ATOMIC(int) killNow;
- althrd_t thread;
-} ALCwasapiPlayback;
+ std::atomic<UINT32> mPadding{0u};
+
+ std::atomic<ALenum> mKillNow{AL_TRUE};
+ std::thread mThread;
+};
-static int ALCwasapiPlayback_mixerProc(void *arg);
+static int ALCwasapiPlayback_mixerProc(ALCwasapiPlayback *self);
static void ALCwasapiPlayback_Construct(ALCwasapiPlayback *self, ALCdevice *device);
static void ALCwasapiPlayback_Destruct(ALCwasapiPlayback *self);
static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *name);
-static HRESULT ALCwasapiPlayback_openProxy(ALCwasapiPlayback *self);
-static void ALCwasapiPlayback_closeProxy(ALCwasapiPlayback *self);
static ALCboolean ALCwasapiPlayback_reset(ALCwasapiPlayback *self);
-static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self);
static ALCboolean ALCwasapiPlayback_start(ALCwasapiPlayback *self);
-static HRESULT ALCwasapiPlayback_startProxy(ALCwasapiPlayback *self);
static void ALCwasapiPlayback_stop(ALCwasapiPlayback *self);
-static void ALCwasapiPlayback_stopProxy(ALCwasapiPlayback *self);
static DECLARE_FORWARD2(ALCwasapiPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
static DECLARE_FORWARD(ALCwasapiPlayback, ALCbackend, ALCuint, availableSamples)
static ClockLatency ALCwasapiPlayback_getClockLatency(ALCwasapiPlayback *self);
@@ -559,78 +531,51 @@ static DECLARE_FORWARD(ALCwasapiPlayback, ALCbackend, void, lock)
static DECLARE_FORWARD(ALCwasapiPlayback, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(ALCwasapiPlayback)
-DEFINE_ALCWASAPIPROXY_VTABLE(ALCwasapiPlayback);
DEFINE_ALCBACKEND_VTABLE(ALCwasapiPlayback);
static void ALCwasapiPlayback_Construct(ALCwasapiPlayback *self, ALCdevice *device)
{
+ new (self) ALCwasapiPlayback{};
SET_VTABLE2(ALCwasapiPlayback, ALCbackend, self);
- SET_VTABLE2(ALCwasapiPlayback, ALCwasapiProxy, self);
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
- ALCwasapiProxy_Construct(STATIC_CAST(ALCwasapiProxy, self));
-
- self->devid = NULL;
-
- self->mmdev = NULL;
- self->client = NULL;
- self->render = NULL;
- self->NotifyEvent = NULL;
-
- self->MsgEvent = NULL;
-
- ATOMIC_INIT(&self->Padding, 0);
-
- ATOMIC_INIT(&self->killNow, 0);
}
static void ALCwasapiPlayback_Destruct(ALCwasapiPlayback *self)
{
- if(self->MsgEvent)
+ if(self->mMsgEvent)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ ThreadRequest req = { self->mMsgEvent, 0 };
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)proxy))
(void)WaitForResponse(&req);
- CloseHandle(self->MsgEvent);
- self->MsgEvent = NULL;
+ CloseHandle(self->mMsgEvent);
+ self->mMsgEvent = nullptr;
}
- if(self->NotifyEvent)
- CloseHandle(self->NotifyEvent);
- self->NotifyEvent = NULL;
-
- free(self->devid);
- self->devid = NULL;
-
- if(self->NotifyEvent != NULL)
- CloseHandle(self->NotifyEvent);
- self->NotifyEvent = NULL;
- if(self->MsgEvent != NULL)
- CloseHandle(self->MsgEvent);
- self->MsgEvent = NULL;
-
- free(self->devid);
- self->devid = NULL;
+ if(self->mNotifyEvent != nullptr)
+ CloseHandle(self->mNotifyEvent);
+ self->mNotifyEvent = nullptr;
+ if(self->mMsgEvent != nullptr)
+ CloseHandle(self->mMsgEvent);
+ self->mMsgEvent = nullptr;
- ALCwasapiProxy_Destruct(STATIC_CAST(ALCwasapiProxy, self));
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+ self->~ALCwasapiPlayback();
}
-FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
+FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(ALCwasapiPlayback *self)
{
- ALCwasapiPlayback *self = arg;
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- UINT32 buffer_len, written;
- ALuint update_size, len;
- BYTE *buffer;
- HRESULT hr;
-
- hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice};
+ IAudioClient *client{self->mClient};
+ IAudioRenderClient *render{self->mRender};
+
+ HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if(FAILED(hr))
{
- ERR("CoInitializeEx(NULL, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr);
+ ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr);
V0(device->Backend,lock)();
aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr);
V0(device->Backend,unlock)();
@@ -640,11 +585,12 @@ FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
SetRTPriority();
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
- update_size = device->UpdateSize;
- buffer_len = update_size * device->NumUpdates;
- while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed))
+ ALuint update_size{device->UpdateSize};
+ UINT32 buffer_len{update_size * device->NumUpdates};
+ while(!self->mKillNow.load(std::memory_order_relaxed))
{
- hr = IAudioClient_GetCurrentPadding(self->client, &written);
+ UINT32 written;
+ hr = client->GetCurrentPadding(&written);
if(FAILED(hr))
{
ERR("Failed to get padding: 0x%08lx\n", hr);
@@ -653,27 +599,28 @@ FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
V0(device->Backend,unlock)();
break;
}
- ATOMIC_STORE(&self->Padding, written, almemory_order_relaxed);
+ self->mPadding.store(written, std::memory_order_relaxed);
- len = buffer_len - written;
+ ALuint len{buffer_len - written};
if(len < update_size)
{
DWORD res;
- res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE);
+ res = WaitForSingleObjectEx(self->mNotifyEvent, 2000, FALSE);
if(res != WAIT_OBJECT_0)
ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
continue;
}
len -= len%update_size;
- hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer);
+ BYTE *buffer;
+ hr = render->GetBuffer(len, &buffer);
if(SUCCEEDED(hr))
{
ALCwasapiPlayback_lock(self);
aluMixData(device, buffer, len);
- ATOMIC_STORE(&self->Padding, written + len, almemory_order_relaxed);
+ self->mPadding.store(written + len, std::memory_order_relaxed);
ALCwasapiPlayback_unlock(self);
- hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0);
+ hr = render->ReleaseBuffer(len, 0);
}
if(FAILED(hr))
{
@@ -684,7 +631,7 @@ FORCE_ALIGN static int ALCwasapiPlayback_mixerProc(void *arg)
break;
}
}
- ATOMIC_STORE(&self->Padding, 0, almemory_order_release);
+ self->mPadding.store(0u, std::memory_order_release);
CoUninitialize();
return 0;
@@ -734,9 +681,9 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
{
HRESULT hr = S_OK;
- self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- if(self->NotifyEvent == NULL || self->MsgEvent == NULL)
+ self->mNotifyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
+ self->mMsgEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
+ if(self->mNotifyEvent == nullptr || self->mMsgEvent == nullptr)
{
ERR("Failed to create message events: %lu\n", GetLastError());
hr = E_FAIL;
@@ -746,40 +693,38 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
{
if(deviceName)
{
- const DevMap *iter;
-
- if(VECTOR_SIZE(PlaybackDevices) == 0)
+ if(PlaybackDevices.empty())
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req = { self->mMsgEvent, 0 };
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE))
(void)WaitForResponse(&req);
}
hr = E_FAIL;
-#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \
- alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0)
- VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
-#undef MATCH_NAME
- if(iter == VECTOR_END(PlaybackDevices))
+ auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
+ [deviceName](const DevMap &entry) -> bool
+ { return entry.name == deviceName || entry.endpoint_guid == deviceName; }
+ );
+ if(iter == PlaybackDevices.cend())
{
int len;
- if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0)
+ if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, nullptr, 0)) > 0)
{
- WCHAR *wname = calloc(sizeof(WCHAR), len);
- MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len);
-#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0)
- VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
-#undef MATCH_NAME
- free(wname);
+ std::vector<WCHAR> wname(len);
+ MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname.data(), len);
+ iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
+ [&wname](const DevMap &entry) -> bool
+ { return entry.devid == wname.data(); }
+ );
}
}
- if(iter == VECTOR_END(PlaybackDevices))
+ if(iter == PlaybackDevices.cend())
WARN("Failed to find device name matching \"%s\"\n", deviceName);
else
{
ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- self->devid = strdupW(iter->devid);
- alstr_copy(&device->DeviceName, iter->name);
+ self->mDevId = iter->devid;
+ alstr_copy_range(&device->DeviceName, &*iter->name.cbegin(), &*iter->name.cend());
hr = S_OK;
}
}
@@ -787,10 +732,11 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
if(SUCCEEDED(hr))
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->mMsgEvent, 0 };
+ auto proxy = static_cast<WasapiProxy*>(self);
hr = E_FAIL;
- if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)proxy))
hr = WaitForResponse(&req);
else
ERR("Failed to post thread message: %lu\n", GetLastError());
@@ -798,15 +744,14 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
if(FAILED(hr))
{
- if(self->NotifyEvent != NULL)
- CloseHandle(self->NotifyEvent);
- self->NotifyEvent = NULL;
- if(self->MsgEvent != NULL)
- CloseHandle(self->MsgEvent);
- self->MsgEvent = NULL;
+ if(self->mNotifyEvent != nullptr)
+ CloseHandle(self->mNotifyEvent);
+ self->mNotifyEvent = nullptr;
+ if(self->mMsgEvent != nullptr)
+ CloseHandle(self->mMsgEvent);
+ self->mMsgEvent = nullptr;
- free(self->devid);
- self->devid = NULL;
+ self->mDevId.clear();
ERR("Device init failed: 0x%08lx\n", hr);
return ALC_INVALID_VALUE;
@@ -815,106 +760,104 @@ static ALCenum ALCwasapiPlayback_open(ALCwasapiPlayback *self, const ALCchar *de
return ALC_NO_ERROR;
}
-static HRESULT ALCwasapiPlayback_openProxy(ALCwasapiPlayback *self)
+HRESULT ALCwasapiPlayback::openProxy()
{
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- void *ptr;
- HRESULT hr;
+ ALCdevice *device = STATIC_CAST(ALCbackend, this)->mDevice;
- hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
+ void *ptr;
+ HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, &ptr);
if(SUCCEEDED(hr))
{
- IMMDeviceEnumerator *Enumerator = ptr;
- if(!self->devid)
- hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &self->mmdev);
+ auto Enumerator = reinterpret_cast<IMMDeviceEnumerator*>(ptr);
+ if(mDevId.empty())
+ hr = Enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &mMMDev);
else
- hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev);
- IMMDeviceEnumerator_Release(Enumerator);
- Enumerator = NULL;
+ hr = Enumerator->GetDevice(mDevId.c_str(), &mMMDev);
+ Enumerator->Release();
}
if(SUCCEEDED(hr))
- hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
+ hr = mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr);
if(SUCCEEDED(hr))
{
- self->client = ptr;
+ mClient = reinterpret_cast<IAudioClient*>(ptr);
if(alstr_empty(device->DeviceName))
- get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL);
+ {
+ std::string devname;
+ std::tie(devname, std::ignore) = get_device_name_and_guid(mMMDev);
+ alstr_copy_range(&device->DeviceName, &*devname.cbegin(), &*devname.cend());
+ }
}
if(FAILED(hr))
{
- if(self->mmdev)
- IMMDevice_Release(self->mmdev);
- self->mmdev = NULL;
+ if(mMMDev)
+ mMMDev->Release();
+ mMMDev = nullptr;
}
return hr;
}
-
-static void ALCwasapiPlayback_closeProxy(ALCwasapiPlayback *self)
+void ALCwasapiPlayback::closeProxy()
{
- if(self->client)
- IAudioClient_Release(self->client);
- self->client = NULL;
+ if(mClient)
+ mClient->Release();
+ mClient = nullptr;
- if(self->mmdev)
- IMMDevice_Release(self->mmdev);
- self->mmdev = NULL;
+ if(mMMDev)
+ mMMDev->Release();
+ mMMDev = nullptr;
}
static ALCboolean ALCwasapiPlayback_reset(ALCwasapiPlayback *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- HRESULT hr = E_FAIL;
+ ThreadRequest req{ self->mMsgEvent, 0 };
+ HRESULT hr{E_FAIL};
- if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)proxy))
hr = WaitForResponse(&req);
return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
}
-static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
+HRESULT ALCwasapiPlayback::resetProxy()
{
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- EndpointFormFactor formfactor = UnknownFormFactor;
- WAVEFORMATEXTENSIBLE OutputType;
- WAVEFORMATEX *wfx = NULL;
- REFERENCE_TIME min_per, buf_time;
- UINT32 buffer_len, min_len;
- void *ptr = NULL;
- HRESULT hr;
+ ALCdevice *device{STATIC_CAST(ALCbackend, this)->mDevice};
- if(self->client)
- IAudioClient_Release(self->client);
- self->client = NULL;
+ if(mClient)
+ mClient->Release();
+ mClient = nullptr;
- hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
+ void *ptr;
+ HRESULT hr = mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr);
if(FAILED(hr))
{
ERR("Failed to reactivate audio client: 0x%08lx\n", hr);
return hr;
}
- self->client = ptr;
+ mClient = reinterpret_cast<IAudioClient*>(ptr);
- hr = IAudioClient_GetMixFormat(self->client, &wfx);
+ WAVEFORMATEX *wfx;
+ hr = mClient->GetMixFormat(&wfx);
if(FAILED(hr))
{
ERR("Failed to get mix format: 0x%08lx\n", hr);
return hr;
}
+ WAVEFORMATEXTENSIBLE OutputType;
if(!MakeExtensible(&OutputType, wfx))
{
CoTaskMemFree(wfx);
return E_FAIL;
}
CoTaskMemFree(wfx);
- wfx = NULL;
+ wfx = nullptr;
- buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC,
- device->Frequency);
+ REFERENCE_TIME buf_time{ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC,
+ device->Frequency)};
if(!(device->Flags&DEVICE_FREQUENCY_REQUEST))
device->Frequency = OutputType.Format.nSamplesPerSec;
@@ -1011,11 +954,11 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec *
OutputType.Format.nBlockAlign;
- hr = IAudioClient_IsFormatSupported(self->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx);
+ hr = mClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx);
if(FAILED(hr))
{
ERR("Failed to check format support: 0x%08lx\n", hr);
- hr = IAudioClient_GetMixFormat(self->client, &wfx);
+ hr = mClient->GetMixFormat(&wfx);
}
if(FAILED(hr))
{
@@ -1023,7 +966,7 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
return hr;
}
- if(wfx != NULL)
+ if(wfx != nullptr)
{
if(!MakeExtensible(&OutputType, wfx))
{
@@ -1031,7 +974,7 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
return E_FAIL;
}
CoTaskMemFree(wfx);
- wfx = NULL;
+ wfx = nullptr;
device->Frequency = OutputType.Format.nSamplesPerSec;
if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO)
@@ -1056,7 +999,7 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
OutputType.dwChannelMask = STEREO;
}
- if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
+ if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_PCM))
{
if(OutputType.Format.wBitsPerSample == 8)
device->FmtType = DevFmtUByte;
@@ -1070,7 +1013,7 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
OutputType.Format.wBitsPerSample = 16;
}
}
- else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
+ else if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
{
device->FmtType = DevFmtFloat;
OutputType.Format.wBitsPerSample = 32;
@@ -1084,30 +1027,33 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
}
OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
}
- get_device_formfactor(self->mmdev, &formfactor);
+
+ EndpointFormFactor formfactor = UnknownFormFactor;
+ get_device_formfactor(mMMDev, &formfactor);
device->IsHeadphones = (device->FmtChans == DevFmtStereo &&
(formfactor == Headphones || formfactor == Headset)
);
SetDefaultWFXChannelOrder(device);
- hr = IAudioClient_Initialize(self->client, AUDCLNT_SHAREMODE_SHARED,
- AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
- buf_time, 0, &OutputType.Format, NULL);
+ hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+ buf_time, 0, &OutputType.Format, nullptr);
if(FAILED(hr))
{
ERR("Failed to initialize audio client: 0x%08lx\n", hr);
return hr;
}
- hr = IAudioClient_GetDevicePeriod(self->client, &min_per, NULL);
+ UINT32 buffer_len, min_len;
+ REFERENCE_TIME min_per;
+ hr = mClient->GetDevicePeriod(&min_per, nullptr);
if(SUCCEEDED(hr))
{
min_len = (UINT32)ScaleCeil(min_per, device->Frequency, REFTIME_PER_SEC);
/* Find the nearest multiple of the period size to the update size */
if(min_len < device->UpdateSize)
min_len *= (device->UpdateSize + min_len/2)/min_len;
- hr = IAudioClient_GetBufferSize(self->client, &buffer_len);
+ hr = mClient->GetBufferSize(&buffer_len);
}
if(FAILED(hr))
{
@@ -1124,7 +1070,7 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
device->UpdateSize = buffer_len / device->NumUpdates;
}
- hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent);
+ hr = mClient->SetEventHandle(mNotifyEvent);
if(FAILED(hr))
{
ERR("Failed to set event handle: 0x%08lx\n", hr);
@@ -1137,77 +1083,81 @@ static HRESULT ALCwasapiPlayback_resetProxy(ALCwasapiPlayback *self)
static ALCboolean ALCwasapiPlayback_start(ALCwasapiPlayback *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- HRESULT hr = E_FAIL;
+ ThreadRequest req{ self->mMsgEvent, 0 };
+ HRESULT hr{E_FAIL};
- if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)proxy))
hr = WaitForResponse(&req);
return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
}
-static HRESULT ALCwasapiPlayback_startProxy(ALCwasapiPlayback *self)
+HRESULT ALCwasapiPlayback::startProxy()
{
- HRESULT hr;
- void *ptr;
+ ResetEvent(mNotifyEvent);
- ResetEvent(self->NotifyEvent);
- hr = IAudioClient_Start(self->client);
+ HRESULT hr = mClient->Start();
if(FAILED(hr))
+ {
ERR("Failed to start audio client: 0x%08lx\n", hr);
+ return hr;
+ }
- if(SUCCEEDED(hr))
- hr = IAudioClient_GetService(self->client, &IID_IAudioRenderClient, &ptr);
+ void *ptr;
+ hr = mClient->GetService(IID_IAudioRenderClient, &ptr);
if(SUCCEEDED(hr))
{
- self->render = ptr;
- ATOMIC_STORE(&self->killNow, 0, almemory_order_release);
- if(althrd_create(&self->thread, ALCwasapiPlayback_mixerProc, self) != althrd_success)
- {
- if(self->render)
- IAudioRenderClient_Release(self->render);
- self->render = NULL;
- IAudioClient_Stop(self->client);
+ mRender = reinterpret_cast<IAudioRenderClient*>(ptr);
+ try {
+ mKillNow.store(AL_FALSE, std::memory_order_release);
+ mThread = std::thread(ALCwasapiPlayback_mixerProc, this);
+ }
+ catch(...) {
+ mRender->Release();
+ mRender = nullptr;
ERR("Failed to start thread\n");
hr = E_FAIL;
}
}
+ if(FAILED(hr))
+ mClient->Stop();
+
return hr;
}
static void ALCwasapiPlayback_stop(ALCwasapiPlayback *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ ThreadRequest req{ self->mMsgEvent, 0 };
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)proxy))
(void)WaitForResponse(&req);
}
-static void ALCwasapiPlayback_stopProxy(ALCwasapiPlayback *self)
+void ALCwasapiPlayback::stopProxy()
{
- int res;
-
- if(!self->render)
+ if(!mRender || !mThread.joinable())
return;
- ATOMIC_STORE_SEQ(&self->killNow, 1);
- althrd_join(self->thread, &res);
+ mKillNow.store(AL_TRUE);
+ mThread.join();
- IAudioRenderClient_Release(self->render);
- self->render = NULL;
- IAudioClient_Stop(self->client);
+ mRender->Release();
+ mRender = nullptr;
+ mClient->Stop();
}
static ClockLatency ALCwasapiPlayback_getClockLatency(ALCwasapiPlayback *self)
{
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
ClockLatency ret;
ALCwasapiPlayback_lock(self);
+ ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice};
ret.ClockTime = GetDeviceClockTime(device);
- ret.Latency = ATOMIC_LOAD(&self->Padding, almemory_order_relaxed) * DEVICE_CLOCK_RES /
+ ret.Latency = self->mPadding.load(std::memory_order_relaxed) * DEVICE_CLOCK_RES /
device->Frequency;
ALCwasapiPlayback_unlock(self);
@@ -1215,40 +1165,39 @@ static ClockLatency ALCwasapiPlayback_getClockLatency(ALCwasapiPlayback *self)
}
-typedef struct ALCwasapiCapture {
- DERIVE_FROM_TYPE(ALCbackend);
- DERIVE_FROM_TYPE(ALCwasapiProxy);
+struct ALCwasapiCapture final : public ALCbackend, WasapiProxy {
+ HRESULT openProxy() override;
+ void closeProxy() override;
- WCHAR *devid;
+ HRESULT resetProxy() override;
+ HRESULT startProxy() override;
+ void stopProxy() override;
- IMMDevice *mmdev;
- IAudioClient *client;
- IAudioCaptureClient *capture;
- HANDLE NotifyEvent;
+ std::wstring mDevId;
- HANDLE MsgEvent;
+ IMMDevice *mMMDev{nullptr};
+ IAudioClient *mClient{nullptr};
+ IAudioCaptureClient *mCapture{nullptr};
+ HANDLE mNotifyEvent{nullptr};
- ChannelConverter *ChannelConv;
- SampleConverter *SampleConv;
- ll_ringbuffer_t *Ring;
+ HANDLE mMsgEvent{nullptr};
- ATOMIC(int) killNow;
- althrd_t thread;
-} ALCwasapiCapture;
+ ChannelConverter *mChannelConv{nullptr};
+ SampleConverter *mSampleConv{nullptr};
+ ll_ringbuffer_t *mRing{nullptr};
+
+ std::atomic<int> mKillNow{AL_TRUE};
+ std::thread mThread;
+};
-static int ALCwasapiCapture_recordProc(void *arg);
+static int ALCwasapiCapture_recordProc(ALCwasapiCapture *self);
static void ALCwasapiCapture_Construct(ALCwasapiCapture *self, ALCdevice *device);
static void ALCwasapiCapture_Destruct(ALCwasapiCapture *self);
static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *name);
-static HRESULT ALCwasapiCapture_openProxy(ALCwasapiCapture *self);
-static void ALCwasapiCapture_closeProxy(ALCwasapiCapture *self);
static DECLARE_FORWARD(ALCwasapiCapture, ALCbackend, ALCboolean, reset)
-static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self);
static ALCboolean ALCwasapiCapture_start(ALCwasapiCapture *self);
-static HRESULT ALCwasapiCapture_startProxy(ALCwasapiCapture *self);
static void ALCwasapiCapture_stop(ALCwasapiCapture *self);
-static void ALCwasapiCapture_stopProxy(ALCwasapiCapture *self);
static ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples);
static ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self);
static DECLARE_FORWARD(ALCwasapiCapture, ALCbackend, ClockLatency, getClockLatency)
@@ -1256,75 +1205,53 @@ static DECLARE_FORWARD(ALCwasapiCapture, ALCbackend, void, lock)
static DECLARE_FORWARD(ALCwasapiCapture, ALCbackend, void, unlock)
DECLARE_DEFAULT_ALLOCATORS(ALCwasapiCapture)
-DEFINE_ALCWASAPIPROXY_VTABLE(ALCwasapiCapture);
DEFINE_ALCBACKEND_VTABLE(ALCwasapiCapture);
static void ALCwasapiCapture_Construct(ALCwasapiCapture *self, ALCdevice *device)
{
+ new (self) ALCwasapiCapture{};
SET_VTABLE2(ALCwasapiCapture, ALCbackend, self);
- SET_VTABLE2(ALCwasapiCapture, ALCwasapiProxy, self);
ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
- ALCwasapiProxy_Construct(STATIC_CAST(ALCwasapiProxy, self));
-
- self->devid = NULL;
-
- self->mmdev = NULL;
- self->client = NULL;
- self->capture = NULL;
- self->NotifyEvent = NULL;
-
- self->MsgEvent = NULL;
-
- self->ChannelConv = NULL;
- self->SampleConv = NULL;
- self->Ring = NULL;
-
- ATOMIC_INIT(&self->killNow, 0);
}
static void ALCwasapiCapture_Destruct(ALCwasapiCapture *self)
{
- if(self->MsgEvent)
+ if(self->mMsgEvent)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ ThreadRequest req{ self->mMsgEvent, 0 };
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)proxy))
(void)WaitForResponse(&req);
- CloseHandle(self->MsgEvent);
- self->MsgEvent = NULL;
+ CloseHandle(self->mMsgEvent);
+ self->mMsgEvent = nullptr;
}
- if(self->NotifyEvent != NULL)
- CloseHandle(self->NotifyEvent);
- self->NotifyEvent = NULL;
+ if(self->mNotifyEvent != nullptr)
+ CloseHandle(self->mNotifyEvent);
+ self->mNotifyEvent = nullptr;
- ll_ringbuffer_free(self->Ring);
- self->Ring = NULL;
+ ll_ringbuffer_free(self->mRing);
+ self->mRing = nullptr;
- DestroySampleConverter(&self->SampleConv);
- DestroyChannelConverter(&self->ChannelConv);
+ DestroySampleConverter(&self->mSampleConv);
+ DestroyChannelConverter(&self->mChannelConv);
- free(self->devid);
- self->devid = NULL;
-
- ALCwasapiProxy_Destruct(STATIC_CAST(ALCwasapiProxy, self));
ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+ self->~ALCwasapiCapture();
}
-FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
+FORCE_ALIGN int ALCwasapiCapture_recordProc(ALCwasapiCapture *self)
{
- ALCwasapiCapture *self = arg;
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- ALfloat *samples = NULL;
- size_t samplesmax = 0;
- HRESULT hr;
+ ALCdevice *device{STATIC_CAST(ALCbackend, self)->mDevice};
+ IAudioCaptureClient *capture{self->mCapture};
- hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if(FAILED(hr))
{
- ERR("CoInitializeEx(NULL, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr);
+ ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr);
V0(device->Backend,lock)();
aluHandleDisconnect(device, "COM init failed: 0x%08lx", hr);
V0(device->Backend,unlock)();
@@ -1333,12 +1260,13 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
althrd_setname(althrd_current(), RECORD_THREAD_NAME);
- while(!ATOMIC_LOAD(&self->killNow, almemory_order_relaxed))
+ std::vector<float> samples;
+ while(!self->mKillNow.load(std::memory_order_relaxed))
{
UINT32 avail;
DWORD res;
- hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail);
+ hr = capture->GetNextPacketSize(&avail);
if(FAILED(hr))
ERR("Failed to get next packet size: 0x%08lx\n", hr);
else if(avail > 0)
@@ -1347,38 +1275,28 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
DWORD flags;
BYTE *rdata;
- hr = IAudioCaptureClient_GetBuffer(self->capture,
- &rdata, &numsamples, &flags, NULL, NULL
- );
+ hr = capture->GetBuffer(&rdata, &numsamples, &flags, nullptr, nullptr);
if(FAILED(hr))
ERR("Failed to get capture buffer: 0x%08lx\n", hr);
else
{
- ll_ringbuffer_data_t data[2];
- size_t dstframes = 0;
-
- if(self->ChannelConv)
+ if(self->mChannelConv)
{
- if(samplesmax < numsamples)
- {
- size_t newmax = RoundUp(numsamples, 4096);
- ALfloat *tmp = al_calloc(DEF_ALIGN, newmax*2*sizeof(ALfloat));
- al_free(samples);
- samples = tmp;
- samplesmax = newmax;
- }
- ChannelConverterInput(self->ChannelConv, rdata, samples, numsamples);
- rdata = (BYTE*)samples;
+ samples.resize(numsamples*2);
+ ChannelConverterInput(self->mChannelConv, rdata, samples.data(), numsamples);
+ rdata = reinterpret_cast<BYTE*>(samples.data());
}
- ll_ringbuffer_get_write_vector(self->Ring, data);
+ ll_ringbuffer_data_t data[2];
+ ll_ringbuffer_get_write_vector(self->mRing, data);
- if(self->SampleConv)
+ size_t dstframes;
+ if(self->mSampleConv)
{
const ALvoid *srcdata = rdata;
ALsizei srcframes = numsamples;
- dstframes = SampleConverterInput(self->SampleConv,
+ dstframes = SampleConverterInput(self->mSampleConv,
&srcdata, &srcframes, data[0].buf, (ALsizei)minz(data[0].len, INT_MAX)
);
if(srcframes > 0 && dstframes == data[0].len && data[1].len > 0)
@@ -1387,7 +1305,7 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
* block was filled, and there's space in the second
* dest block, do another run for the second block.
*/
- dstframes += SampleConverterInput(self->SampleConv,
+ dstframes += SampleConverterInput(self->mSampleConv,
&srcdata, &srcframes, data[1].buf, (ALsizei)minz(data[1].len, INT_MAX)
);
}
@@ -1405,9 +1323,9 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
dstframes = len1 + len2;
}
- ll_ringbuffer_write_advance(self->Ring, dstframes);
+ ll_ringbuffer_write_advance(self->mRing, dstframes);
- hr = IAudioCaptureClient_ReleaseBuffer(self->capture, numsamples);
+ hr = capture->ReleaseBuffer(numsamples);
if(FAILED(hr)) ERR("Failed to release capture buffer: 0x%08lx\n", hr);
}
}
@@ -1420,15 +1338,11 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
break;
}
- res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE);
+ res = WaitForSingleObjectEx(self->mNotifyEvent, 2000, FALSE);
if(res != WAIT_OBJECT_0)
ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
}
- al_free(samples);
- samples = NULL;
- samplesmax = 0;
-
CoUninitialize();
return 0;
}
@@ -1436,11 +1350,11 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(void *arg)
static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *deviceName)
{
- HRESULT hr = S_OK;
+ HRESULT hr{S_OK};
- self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- if(self->NotifyEvent == NULL || self->MsgEvent == NULL)
+ self->mNotifyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
+ self->mMsgEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
+ if(self->mNotifyEvent == nullptr || self->mMsgEvent == nullptr)
{
ERR("Failed to create message events: %lu\n", GetLastError());
hr = E_FAIL;
@@ -1450,40 +1364,38 @@ static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *devi
{
if(deviceName)
{
- const DevMap *iter;
-
- if(VECTOR_SIZE(CaptureDevices) == 0)
+ if(CaptureDevices.empty())
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->mMsgEvent, 0 };
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, CAPTURE_DEVICE_PROBE))
(void)WaitForResponse(&req);
}
hr = E_FAIL;
-#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 || \
- alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0)
- VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
-#undef MATCH_NAME
- if(iter == VECTOR_END(CaptureDevices))
+ auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
+ [deviceName](const DevMap &entry) -> bool
+ { return entry.name == deviceName || entry.endpoint_guid == deviceName; }
+ );
+ if(iter == CaptureDevices.cend())
{
int len;
- if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0)
+ if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, nullptr, 0)) > 0)
{
- WCHAR *wname = calloc(sizeof(WCHAR), len);
- MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len);
-#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0)
- VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
-#undef MATCH_NAME
- free(wname);
+ std::vector<WCHAR> wname(len);
+ MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname.data(), len);
+ iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
+ [&wname](const DevMap &entry) -> bool
+ { return entry.devid == wname.data(); }
+ );
}
}
- if(iter == VECTOR_END(CaptureDevices))
+ if(iter == CaptureDevices.cend())
WARN("Failed to find device name matching \"%s\"\n", deviceName);
else
{
ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
- self->devid = strdupW(iter->devid);
- alstr_copy(&device->DeviceName, iter->name);
+ self->mDevId = iter->devid;
+ alstr_copy_range(&device->DeviceName, &*iter->name.cbegin(), &*iter->name.cend());
hr = S_OK;
}
}
@@ -1491,10 +1403,11 @@ static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *devi
if(SUCCEEDED(hr))
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->mMsgEvent, 0 };
hr = E_FAIL;
- if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)proxy))
hr = WaitForResponse(&req);
else
ERR("Failed to post thread message: %lu\n", GetLastError());
@@ -1502,25 +1415,25 @@ static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *devi
if(FAILED(hr))
{
- if(self->NotifyEvent != NULL)
- CloseHandle(self->NotifyEvent);
- self->NotifyEvent = NULL;
- if(self->MsgEvent != NULL)
- CloseHandle(self->MsgEvent);
- self->MsgEvent = NULL;
+ if(self->mNotifyEvent != nullptr)
+ CloseHandle(self->mNotifyEvent);
+ self->mNotifyEvent = nullptr;
+ if(self->mMsgEvent != nullptr)
+ CloseHandle(self->mMsgEvent);
+ self->mMsgEvent = nullptr;
- free(self->devid);
- self->devid = NULL;
+ self->mDevId.clear();
ERR("Device init failed: 0x%08lx\n", hr);
return ALC_INVALID_VALUE;
}
else
{
- ThreadRequest req = { self->MsgEvent, 0 };
+ ThreadRequest req{ self->mMsgEvent, 0 };
hr = E_FAIL;
- if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)proxy))
hr = WaitForResponse(&req);
else
ERR("Failed to post thread message: %lu\n", GetLastError());
@@ -1536,85 +1449,81 @@ static ALCenum ALCwasapiCapture_open(ALCwasapiCapture *self, const ALCchar *devi
return ALC_NO_ERROR;
}
-static HRESULT ALCwasapiCapture_openProxy(ALCwasapiCapture *self)
+HRESULT ALCwasapiCapture::openProxy()
{
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- void *ptr;
- HRESULT hr;
+ ALCdevice *device{STATIC_CAST(ALCbackend, this)->mDevice};
- hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
+ void *ptr;
+ HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER,
+ IID_IMMDeviceEnumerator, &ptr);
if(SUCCEEDED(hr))
{
- IMMDeviceEnumerator *Enumerator = ptr;
- if(!self->devid)
- hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eCapture, eMultimedia, &self->mmdev);
+ auto Enumerator = reinterpret_cast<IMMDeviceEnumerator*>(ptr);
+ if(mDevId.empty())
+ hr = Enumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &mMMDev);
else
- hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev);
- IMMDeviceEnumerator_Release(Enumerator);
- Enumerator = NULL;
+ hr = Enumerator->GetDevice(mDevId.c_str(), &mMMDev);
+ Enumerator->Release();
}
if(SUCCEEDED(hr))
- hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
+ hr = mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr);
if(SUCCEEDED(hr))
{
- self->client = ptr;
+ mClient = reinterpret_cast<IAudioClient*>(ptr);
if(alstr_empty(device->DeviceName))
- get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL);
+ {
+ std::string devname;
+ std::tie(devname, std::ignore) = get_device_name_and_guid(mMMDev);
+ alstr_copy_range(&device->DeviceName, &*devname.cbegin(), &*devname.cend());
+ }
}
if(FAILED(hr))
{
- if(self->mmdev)
- IMMDevice_Release(self->mmdev);
- self->mmdev = NULL;
+ if(mMMDev)
+ mMMDev->Release();
+ mMMDev = nullptr;
}
return hr;
}
-
-static void ALCwasapiCapture_closeProxy(ALCwasapiCapture *self)
+void ALCwasapiCapture::closeProxy()
{
- if(self->client)
- IAudioClient_Release(self->client);
- self->client = NULL;
+ if(mClient)
+ mClient->Release();
+ mClient = nullptr;
- if(self->mmdev)
- IMMDevice_Release(self->mmdev);
- self->mmdev = NULL;
+ if(mMMDev)
+ mMMDev->Release();
+ mMMDev = nullptr;
}
-
-static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
+HRESULT ALCwasapiCapture::resetProxy()
{
- ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
- WAVEFORMATEXTENSIBLE OutputType;
- WAVEFORMATEX *wfx = NULL;
- enum DevFmtType srcType;
- REFERENCE_TIME buf_time;
- UINT32 buffer_len;
- void *ptr = NULL;
- HRESULT hr;
+ ALCdevice *device{STATIC_CAST(ALCbackend, this)->mDevice};
- if(self->client)
- IAudioClient_Release(self->client);
- self->client = NULL;
+ if(mClient)
+ mClient->Release();
+ mClient = nullptr;
- hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
+ void *ptr;
+ HRESULT hr{mMMDev->Activate(IID_IAudioClient, CLSCTX_INPROC_SERVER, nullptr, &ptr)};
if(FAILED(hr))
{
ERR("Failed to reactivate audio client: 0x%08lx\n", hr);
return hr;
}
- self->client = ptr;
+ mClient = reinterpret_cast<IAudioClient*>(ptr);
- buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC,
- device->Frequency);
+ REFERENCE_TIME buf_time{ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC,
+ device->Frequency)};
// Make sure buffer is at least 100ms in size
buf_time = maxu64(buf_time, REFTIME_PER_SEC/10);
device->UpdateSize = (ALuint)ScaleCeil(buf_time, device->Frequency, REFTIME_PER_SEC) /
device->NumUpdates;
+ WAVEFORMATEXTENSIBLE OutputType;
OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
switch(device->FmtChans)
{
@@ -1682,19 +1591,18 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
OutputType.Format.nBlockAlign;
OutputType.Format.cbSize = sizeof(OutputType) - sizeof(OutputType.Format);
- hr = IAudioClient_IsFormatSupported(self->client,
- AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx
- );
+ WAVEFORMATEX *wfx;
+ hr = mClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx);
if(FAILED(hr))
{
ERR("Failed to check format support: 0x%08lx\n", hr);
return hr;
}
- DestroySampleConverter(&self->SampleConv);
- DestroyChannelConverter(&self->ChannelConv);
+ DestroySampleConverter(&mSampleConv);
+ DestroyChannelConverter(&mChannelConv);
- if(wfx != NULL)
+ if(wfx != nullptr)
{
if(!(wfx->nChannels == OutputType.Format.nChannels ||
(wfx->nChannels == 1 && OutputType.Format.nChannels == 2) ||
@@ -1714,10 +1622,11 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
return E_FAIL;
}
CoTaskMemFree(wfx);
- wfx = NULL;
+ wfx = nullptr;
}
- if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
+ enum DevFmtType srcType;
+ if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_PCM))
{
if(OutputType.Format.wBitsPerSample == 8)
srcType = DevFmtUByte;
@@ -1731,7 +1640,7 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
return E_FAIL;
}
}
- else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
+ else if(IsEqualGUID(OutputType.SubFormat, KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
{
if(OutputType.Format.wBitsPerSample == 32)
srcType = DevFmtFloat;
@@ -1749,9 +1658,8 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
if(device->FmtChans == DevFmtMono && OutputType.Format.nChannels == 2)
{
- self->ChannelConv = CreateChannelConverter(srcType, DevFmtStereo,
- device->FmtChans);
- if(!self->ChannelConv)
+ mChannelConv = CreateChannelConverter(srcType, DevFmtStereo, device->FmtChans);
+ if(!mChannelConv)
{
ERR("Failed to create %s stereo-to-mono converter\n", DevFmtTypeString(srcType));
return E_FAIL;
@@ -1764,9 +1672,8 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
}
else if(device->FmtChans == DevFmtStereo && OutputType.Format.nChannels == 1)
{
- self->ChannelConv = CreateChannelConverter(srcType, DevFmtMono,
- device->FmtChans);
- if(!self->ChannelConv)
+ mChannelConv = CreateChannelConverter(srcType, DevFmtMono, device->FmtChans);
+ if(!mChannelConv)
{
ERR("Failed to create %s mono-to-stereo converter\n", DevFmtTypeString(srcType));
return E_FAIL;
@@ -1777,11 +1684,11 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
if(device->Frequency != OutputType.Format.nSamplesPerSec || device->FmtType != srcType)
{
- self->SampleConv = CreateSampleConverter(
+ mSampleConv = CreateSampleConverter(
srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder),
OutputType.Format.nSamplesPerSec, device->Frequency
);
- if(!self->SampleConv)
+ if(!mSampleConv)
{
ERR("Failed to create converter for %s format, dst: %s %uhz, src: %s %luhz\n",
DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
@@ -1793,17 +1700,16 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec);
}
- hr = IAudioClient_Initialize(self->client,
- AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
- buf_time, 0, &OutputType.Format, NULL
- );
+ hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+ buf_time, 0, &OutputType.Format, nullptr);
if(FAILED(hr))
{
ERR("Failed to initialize audio client: 0x%08lx\n", hr);
return hr;
}
- hr = IAudioClient_GetBufferSize(self->client, &buffer_len);
+ UINT32 buffer_len;
+ hr = mClient->GetBufferSize(&buffer_len);
if(FAILED(hr))
{
ERR("Failed to get buffer size: 0x%08lx\n", hr);
@@ -1811,18 +1717,18 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
}
buffer_len = maxu(device->UpdateSize*device->NumUpdates, buffer_len);
- ll_ringbuffer_free(self->Ring);
- self->Ring = ll_ringbuffer_create(buffer_len,
+ ll_ringbuffer_free(mRing);
+ mRing = ll_ringbuffer_create(buffer_len,
FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder),
false
);
- if(!self->Ring)
+ if(!mRing)
{
ERR("Failed to allocate capture ring buffer\n");
return E_OUTOFMEMORY;
}
- hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent);
+ hr = mClient->SetEventHandle(mNotifyEvent);
if(FAILED(hr))
{
ERR("Failed to set event handle: 0x%08lx\n", hr);
@@ -1835,46 +1741,48 @@ static HRESULT ALCwasapiCapture_resetProxy(ALCwasapiCapture *self)
static ALCboolean ALCwasapiCapture_start(ALCwasapiCapture *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- HRESULT hr = E_FAIL;
+ ThreadRequest req{ self->mMsgEvent, 0 };
+ HRESULT hr{E_FAIL};
- if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)proxy))
hr = WaitForResponse(&req);
return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
}
-static HRESULT ALCwasapiCapture_startProxy(ALCwasapiCapture *self)
+HRESULT ALCwasapiCapture::startProxy()
{
- HRESULT hr;
- void *ptr;
+ ResetEvent(mNotifyEvent);
- ResetEvent(self->NotifyEvent);
- hr = IAudioClient_Start(self->client);
+ HRESULT hr{mClient->Start()};
if(FAILED(hr))
{
ERR("Failed to start audio client: 0x%08lx\n", hr);
return hr;
}
- hr = IAudioClient_GetService(self->client, &IID_IAudioCaptureClient, &ptr);
+ void *ptr;
+ hr = mClient->GetService(IID_IAudioCaptureClient, &ptr);
if(SUCCEEDED(hr))
{
- self->capture = ptr;
- ATOMIC_STORE(&self->killNow, 0, almemory_order_release);
- if(althrd_create(&self->thread, ALCwasapiCapture_recordProc, self) != althrd_success)
- {
+ mCapture = reinterpret_cast<IAudioCaptureClient*>(ptr);
+ try {
+ mKillNow.store(AL_FALSE, std::memory_order_release);
+ mThread = std::thread(ALCwasapiCapture_recordProc, this);
+ }
+ catch(...) {
+ mCapture->Release();
+ mCapture = nullptr;
ERR("Failed to start thread\n");
- IAudioCaptureClient_Release(self->capture);
- self->capture = NULL;
hr = E_FAIL;
}
}
if(FAILED(hr))
{
- IAudioClient_Stop(self->client);
- IAudioClient_Reset(self->client);
+ mClient->Stop();
+ mClient->Reset();
}
return hr;
@@ -1883,46 +1791,45 @@ static HRESULT ALCwasapiCapture_startProxy(ALCwasapiCapture *self)
static void ALCwasapiCapture_stop(ALCwasapiCapture *self)
{
- ThreadRequest req = { self->MsgEvent, 0 };
- if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCwasapiProxy, self)))
+ ThreadRequest req{ self->mMsgEvent, 0 };
+ auto proxy = static_cast<WasapiProxy*>(self);
+ if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)proxy))
(void)WaitForResponse(&req);
}
-static void ALCwasapiCapture_stopProxy(ALCwasapiCapture *self)
+void ALCwasapiCapture::stopProxy()
{
- int res;
-
- if(!self->capture)
+ if(!mCapture || !mThread.joinable())
return;
- ATOMIC_STORE_SEQ(&self->killNow, 1);
- althrd_join(self->thread, &res);
+ mKillNow.store(AL_TRUE);
+ mThread.join();
- IAudioCaptureClient_Release(self->capture);
- self->capture = NULL;
- IAudioClient_Stop(self->client);
- IAudioClient_Reset(self->client);
+ mCapture->Release();
+ mCapture = nullptr;
+ mClient->Stop();
+ mClient->Reset();
}
-ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self)
+static ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self)
{
- return (ALuint)ll_ringbuffer_read_space(self->Ring);
+ return (ALuint)ll_ringbuffer_read_space(self->mRing);
}
-ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples)
+static ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples)
{
if(ALCwasapiCapture_availableSamples(self) < samples)
return ALC_INVALID_VALUE;
- ll_ringbuffer_read(self->Ring, buffer, samples);
+ ll_ringbuffer_read(self->mRing, reinterpret_cast<char*>(buffer), samples);
return ALC_NO_ERROR;
}
-typedef struct ALCwasapiBackendFactory {
- DERIVE_FROM_TYPE(ALCbackendFactory);
-} ALCwasapiBackendFactory;
-#define ALCWASAPIBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCwasapiBackendFactory, ALCbackendFactory) } }
+struct ALCwasapiBackendFactory final : public ALCbackendFactory {
+ ALCwasapiBackendFactory() noexcept;
+};
+#define ALCWASAPIBACKENDFACTORY_INITIALIZER GET_VTABLE2(ALCwasapiBackendFactory, ALCbackendFactory)
static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory *self);
static void ALCwasapiBackendFactory_deinit(ALCwasapiBackendFactory *self);
@@ -1932,26 +1839,28 @@ static ALCbackend* ALCwasapiBackendFactory_createBackend(ALCwasapiBackendFactory
DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwasapiBackendFactory);
+ALCwasapiBackendFactory::ALCwasapiBackendFactory() noexcept
+ : ALCbackendFactory{ALCWASAPIBACKENDFACTORY_INITIALIZER}
+{
+}
+
static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory* UNUSED(self))
{
static HRESULT InitResult;
- VECTOR_INIT(PlaybackDevices);
- VECTOR_INIT(CaptureDevices);
-
if(!ThreadHdl)
{
ThreadRequest req;
InitResult = E_FAIL;
- req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL);
- if(req.FinishedEvt == NULL)
+ req.FinishedEvt = CreateEventW(nullptr, FALSE, FALSE, nullptr);
+ if(req.FinishedEvt == nullptr)
ERR("Failed to create event: %lu\n", GetLastError());
else
{
- ThreadHdl = CreateThread(NULL, 0, ALCwasapiProxy_messageHandler, &req, 0, &ThreadID);
- if(ThreadHdl != NULL)
+ ThreadHdl = CreateThread(nullptr, 0, WasapiProxy_messageHandler, &req, 0, &ThreadID);
+ if(ThreadHdl != nullptr)
InitResult = WaitForResponse(&req);
CloseHandle(req.FinishedEvt);
}
@@ -1962,18 +1871,15 @@ static ALCboolean ALCwasapiBackendFactory_init(ALCwasapiBackendFactory* UNUSED(s
static void ALCwasapiBackendFactory_deinit(ALCwasapiBackendFactory* UNUSED(self))
{
- clear_devlist(&PlaybackDevices);
- VECTOR_DEINIT(PlaybackDevices);
-
- clear_devlist(&CaptureDevices);
- VECTOR_DEINIT(CaptureDevices);
+ PlaybackDevices.clear();
+ CaptureDevices.clear();
if(ThreadHdl)
{
TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID);
PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
CloseHandle(ThreadHdl);
- ThreadHdl = NULL;
+ ThreadHdl = nullptr;
}
}
@@ -1986,34 +1892,37 @@ static ALCboolean ALCwasapiBackendFactory_querySupport(ALCwasapiBackendFactory*
static void ALCwasapiBackendFactory_probe(ALCwasapiBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
{
- ThreadRequest req = { NULL, 0 };
+ ThreadRequest req{ nullptr, 0 };
- req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL);
- if(req.FinishedEvt == NULL)
+ req.FinishedEvt = CreateEventW(nullptr, FALSE, FALSE, nullptr);
+ if(req.FinishedEvt == nullptr)
ERR("Failed to create event: %lu\n", GetLastError());
else
{
+ auto add_device = [outnames](const DevMap &entry) -> void
+ {
+ const char *name{entry.name.c_str()};
+ size_t namelen{entry.name.length()};
+ /* +1 to also append the null char (to ensure a null-separated list
+ * and double-null terminated list).
+ */
+ alstr_append_range(outnames, name, name + namelen+1);
+ };
HRESULT hr = E_FAIL;
if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type))
hr = WaitForResponse(&req);
if(SUCCEEDED(hr)) switch(type)
{
-#define APPEND_OUTNAME(e) do { \
- if(!alstr_empty((e)->name)) \
- alstr_append_range(outnames, VECTOR_BEGIN((e)->name), \
- VECTOR_END((e)->name)+1); \
-} while(0)
case ALL_DEVICE_PROBE:
- VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_OUTNAME);
+ std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device);
break;
case CAPTURE_DEVICE_PROBE:
- VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_OUTNAME);
+ std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device);
break;
-#undef APPEND_OUTNAME
}
CloseHandle(req.FinishedEvt);
- req.FinishedEvt = NULL;
+ req.FinishedEvt = nullptr;
}
}
@@ -2023,23 +1932,23 @@ static ALCbackend* ALCwasapiBackendFactory_createBackend(ALCwasapiBackendFactory
{
ALCwasapiPlayback *backend;
NEW_OBJ(backend, ALCwasapiPlayback)(device);
- if(!backend) return NULL;
+ if(!backend) return nullptr;
return STATIC_CAST(ALCbackend, backend);
}
if(type == ALCbackend_Capture)
{
ALCwasapiCapture *backend;
NEW_OBJ(backend, ALCwasapiCapture)(device);
- if(!backend) return NULL;
+ if(!backend) return nullptr;
return STATIC_CAST(ALCbackend, backend);
}
- return NULL;
+ return nullptr;
}
ALCbackendFactory *ALCwasapiBackendFactory_getFactory(void)
{
- static ALCwasapiBackendFactory factory = ALCWASAPIBACKENDFACTORY_INITIALIZER;
+ static ALCwasapiBackendFactory factory{};
return STATIC_CAST(ALCbackendFactory, &factory);
}
diff --git a/Alc/bformatdec.c b/Alc/bformatdec.cpp
index 5233d06f..7d1e36ff 100644
--- a/Alc/bformatdec.c
+++ b/Alc/bformatdec.cpp
@@ -1,6 +1,9 @@
#include "config.h"
+#include <array>
+#include <vector>
+
#include "bformatdec.h"
#include "ambdec.h"
#include "filters/splitter.h"
@@ -56,12 +59,14 @@ const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
};
+namespace {
+
#define HF_BAND 0
#define LF_BAND 1
#define NUM_BANDS 2
/* These points are in AL coordinates! */
-static const ALfloat Ambi3DPoints[8][3] = {
+constexpr ALfloat Ambi3DPoints[8][3] = {
{ -0.577350269f, 0.577350269f, -0.577350269f },
{ 0.577350269f, 0.577350269f, -0.577350269f },
{ -0.577350269f, 0.577350269f, 0.577350269f },
@@ -71,7 +76,7 @@ static const ALfloat Ambi3DPoints[8][3] = {
{ -0.577350269f, -0.577350269f, 0.577350269f },
{ 0.577350269f, -0.577350269f, 0.577350269f },
};
-static const ALfloat Ambi3DDecoder[8][MAX_AMBI_COEFFS] = {
+constexpr ALfloat Ambi3DDecoder[8][MAX_AMBI_COEFFS] = {
{ 0.125f, 0.125f, 0.125f, 0.125f },
{ 0.125f, -0.125f, 0.125f, 0.125f },
{ 0.125f, 0.125f, 0.125f, -0.125f },
@@ -81,14 +86,61 @@ static const ALfloat Ambi3DDecoder[8][MAX_AMBI_COEFFS] = {
{ 0.125f, 0.125f, -0.125f, -0.125f },
{ 0.125f, -0.125f, -0.125f, -0.125f },
};
-static const ALfloat Ambi3DDecoderHFScale[MAX_AMBI_COEFFS] = {
+constexpr ALfloat Ambi3DDecoderHFScale[MAX_AMBI_COEFFS] = {
2.0f,
1.15470054f, 1.15470054f, 1.15470054f
};
+#define INVALID_UPSAMPLE_INDEX INT_MAX
+ALsizei GetACNIndex(const BFChannelConfig *chans, ALsizei numchans, ALsizei acn)
+{
+ ALsizei i;
+ for(i = 0;i < numchans;i++)
+ {
+ if(chans[i].Index == acn)
+ return i;
+ }
+ return INVALID_UPSAMPLE_INDEX;
+}
+#define GetChannelForACN(b, a) GetACNIndex((b).Ambi.Map, (b).NumChannels, (a))
+
+
+template<typename T, size_t alignment>
+class aligned_allocator : public std::allocator<T> {
+public:
+ using size_type = size_t;
+ using pointer = T*;
+ using const_pointer = const T*;
+
+ template<typename U>
+ struct rebind {
+ using other = aligned_allocator<U, alignment>;
+ };
+
+ pointer allocate(size_type n, const void* = nullptr)
+ { return reinterpret_cast<T*>(al_malloc(alignment, n*sizeof(T))); }
+
+ void deallocate(pointer p, size_type)
+ { al_free(p); }
+
+ aligned_allocator() : std::allocator<T>() { }
+ aligned_allocator(const aligned_allocator &a) : std::allocator<T>(a) { }
+ template<class U>
+ aligned_allocator(const aligned_allocator<U,alignment> &a)
+ : std::allocator<T>(a)
+ { }
+ ~aligned_allocator() { }
+};
+
+template<typename T, size_t alignment>
+using aligned_vector = std::vector<T, aligned_allocator<T, alignment>>;
+
+} // namespace
+
+
/* NOTE: BandSplitter filters are unused with single-band decoding */
-typedef struct BFormatDec {
+struct BFormatDec {
ALuint Enabled; /* Bitfield of enabled channels. */
union {
@@ -98,10 +150,10 @@ typedef struct BFormatDec {
BandSplitter XOver[MAX_AMBI_COEFFS];
- ALfloat (*Samples)[BUFFERSIZE];
+ aligned_vector<std::array<ALfloat,BUFFERSIZE>, 16> Samples;
/* These two alias into Samples */
- ALfloat (*SamplesHF)[BUFFERSIZE];
- ALfloat (*SamplesLF)[BUFFERSIZE];
+ std::array<ALfloat,BUFFERSIZE> *SamplesHF;
+ std::array<ALfloat,BUFFERSIZE> *SamplesLF;
alignas(16) ALfloat ChannelMix[BUFFERSIZE];
@@ -112,30 +164,26 @@ typedef struct BFormatDec {
ALsizei NumChannels;
ALboolean DualBand;
-} BFormatDec;
+
+ void *operator new(size_t size) { return al_malloc(alignof(BFormatDec), size); }
+ void operator delete(void *block) { al_free(block); }
+};
BFormatDec *bformatdec_alloc()
-{
- return al_calloc(16, sizeof(BFormatDec));
-}
+{ return new BFormatDec{}; }
void bformatdec_free(BFormatDec **dec)
{
if(dec && *dec)
{
- al_free((*dec)->Samples);
- (*dec)->Samples = NULL;
- (*dec)->SamplesHF = NULL;
- (*dec)->SamplesLF = NULL;
-
- al_free(*dec);
- *dec = NULL;
+ delete *dec;
+ *dec = nullptr;
}
}
void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount, ALuint srate, const ALsizei chanmap[MAX_OUTPUT_CHANNELS])
{
- static const ALsizei map2DTo3D[MAX_AMBI2D_COEFFS] = {
+ static constexpr ALsizei map2DTo3D[MAX_AMBI2D_COEFFS] = {
0, 1, 3, 4, 8, 9, 15
};
const ALfloat *coeff_scale = N3D2N3DScale;
@@ -143,23 +191,22 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
ALfloat ratio;
ALsizei i;
- al_free(dec->Samples);
- dec->Samples = NULL;
- dec->SamplesHF = NULL;
- dec->SamplesLF = NULL;
+ dec->Samples.clear();
+ dec->SamplesHF = nullptr;
+ dec->SamplesLF = nullptr;
dec->NumChannels = chancount;
- dec->Samples = al_calloc(16, dec->NumChannels*2 * sizeof(dec->Samples[0]));
- dec->SamplesHF = dec->Samples;
+ dec->Samples.resize(dec->NumChannels * 2);
+ dec->SamplesHF = dec->Samples.data();
dec->SamplesLF = dec->SamplesHF + dec->NumChannels;
dec->Enabled = 0;
for(i = 0;i < conf->NumSpeakers;i++)
dec->Enabled |= 1 << chanmap[i];
- if(conf->CoeffScale == ADS_SN3D)
+ if(conf->CoeffScale == AmbDecScale::SN3D)
coeff_scale = SN3D2N3DScale;
- else if(conf->CoeffScale == ADS_FuMa)
+ else if(conf->CoeffScale == AmbDecScale::FuMa)
coeff_scale = FuMa2N3DScale;
memset(dec->UpSampler, 0, sizeof(dec->UpSampler));
@@ -304,15 +351,14 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
}
-void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
+void bformatdec_process(struct BFormatDec *dec, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*RESTRICT InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
{
ALsizei chan, i;
- OutBuffer = ASSUME_ALIGNED(OutBuffer, 16);
if(dec->DualBand)
{
for(i = 0;i < dec->NumChannels;i++)
- bandsplit_process(&dec->XOver[i], dec->SamplesHF[i], dec->SamplesLF[i],
+ bandsplit_process(&dec->XOver[i], dec->SamplesHF[i].data(), dec->SamplesLF[i].data(),
InSamples[i], SamplesToDo);
for(chan = 0;chan < OutChannels;chan++)
@@ -322,10 +368,12 @@ void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BU
memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
MixRowSamples(dec->ChannelMix, dec->Matrix.Dual[chan][HF_BAND],
- dec->SamplesHF, dec->NumChannels, 0, SamplesToDo
+ &reinterpret_cast<ALfloat(&)[BUFFERSIZE]>(dec->SamplesHF[0]),
+ dec->NumChannels, 0, SamplesToDo
);
MixRowSamples(dec->ChannelMix, dec->Matrix.Dual[chan][LF_BAND],
- dec->SamplesLF, dec->NumChannels, 0, SamplesToDo
+ &reinterpret_cast<ALfloat(&)[BUFFERSIZE]>(dec->SamplesLF[0]),
+ dec->NumChannels, 0, SamplesToDo
);
for(i = 0;i < SamplesToDo;i++)
@@ -350,7 +398,7 @@ void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BU
}
-void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei InChannels, ALsizei SamplesToDo)
+void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE], const ALfloat (*RESTRICT InSamples)[BUFFERSIZE], ALsizei InChannels, ALsizei SamplesToDo)
{
ALsizei i;
@@ -370,51 +418,39 @@ void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[B
* bands.
*/
bandsplit_process(&dec->UpSampler[i].XOver,
- dec->Samples[HF_BAND], dec->Samples[LF_BAND],
+ dec->Samples[HF_BAND].data(), dec->Samples[LF_BAND].data(),
InSamples[i], SamplesToDo
);
/* Now write each band to the output. */
MixRowSamples(OutBuffer[i], dec->UpSampler[i].Gains,
- dec->Samples, NUM_BANDS, 0, SamplesToDo
+ &reinterpret_cast<ALfloat(&)[BUFFERSIZE]>(dec->Samples[0]),
+ NUM_BANDS, 0, SamplesToDo
);
}
}
-#define INVALID_UPSAMPLE_INDEX INT_MAX
-
-static ALsizei GetACNIndex(const BFChannelConfig *chans, ALsizei numchans, ALsizei acn)
-{
- ALsizei i;
- for(i = 0;i < numchans;i++)
- {
- if(chans[i].Index == acn)
- return i;
- }
- return INVALID_UPSAMPLE_INDEX;
-}
-#define GetChannelForACN(b, a) GetACNIndex((b).Ambi.Map, (b).NumChannels, (a))
-
-typedef struct AmbiUpsampler {
+struct AmbiUpsampler {
alignas(16) ALfloat Samples[NUM_BANDS][BUFFERSIZE];
BandSplitter XOver[4];
ALfloat Gains[4][MAX_OUTPUT_CHANNELS][NUM_BANDS];
-} AmbiUpsampler;
+
+ void *operator new(size_t size) { return al_malloc(alignof(AmbiUpsampler), size); }
+ void operator delete(void *block) { al_free(block); }
+};
AmbiUpsampler *ambiup_alloc()
-{
- return al_calloc(16, sizeof(AmbiUpsampler));
-}
+{ return new AmbiUpsampler{}; }
void ambiup_free(struct AmbiUpsampler **ambiup)
{
if(ambiup)
{
- al_free(*ambiup);
- *ambiup = NULL;
+ delete *ambiup;
+ *ambiup = nullptr;
}
}
@@ -473,7 +509,7 @@ void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device, ALfloat
}
}
-void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
+void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*RESTRICT InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
{
ALsizei i, j;
diff --git a/Alc/bformatdec.h b/Alc/bformatdec.h
index 2d7d1d62..964a89f9 100644
--- a/Alc/bformatdec.h
+++ b/Alc/bformatdec.h
@@ -3,6 +3,9 @@
#include "alMain.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
/* These are the necessary scales for first-order HF responses to play over
* higher-order 2D (non-periphonic) decoders.
@@ -24,9 +27,9 @@
/* NOTE: These are scale factors as applied to Ambisonics content. Decoder
* coefficients should be divided by these values to get proper N3D scalings.
*/
-const ALfloat N3D2N3DScale[MAX_AMBI_COEFFS];
-const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS];
-const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS];
+extern const ALfloat N3D2N3DScale[MAX_AMBI_COEFFS];
+extern const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS];
+extern const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS];
struct AmbDecConf;
@@ -39,10 +42,10 @@ void bformatdec_free(struct BFormatDec **dec);
void bformatdec_reset(struct BFormatDec *dec, const struct AmbDecConf *conf, ALsizei chancount, ALuint srate, const ALsizei chanmap[MAX_OUTPUT_CHANNELS]);
/* Decodes the ambisonic input to the given output channels. */
-void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
+void bformatdec_process(struct BFormatDec *dec, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*RESTRICT InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
/* Up-samples a first-order input to the decoder's configuration. */
-void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei InChannels, ALsizei SamplesToDo);
+void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE], const ALfloat (*RESTRICT InSamples)[BUFFERSIZE], ALsizei InChannels, ALsizei SamplesToDo);
/* Stand-alone first-order upsampler. Kept here because it shares some stuff
@@ -52,6 +55,10 @@ struct AmbiUpsampler *ambiup_alloc();
void ambiup_free(struct AmbiUpsampler **ambiup);
void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device, ALfloat w_scale, ALfloat xyz_scale);
-void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
+void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*RESTRICT InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
#endif /* BFORMATDEC_H */
diff --git a/Alc/bs2b.c b/Alc/bs2b.c
index e235e547..e0ce3249 100644
--- a/Alc/bs2b.c
+++ b/Alc/bs2b.c
@@ -129,7 +129,7 @@ void bs2b_clear(struct bs2b *bs2b)
memset(&bs2b->last_sample, 0, sizeof(bs2b->last_sample));
} /* bs2b_clear */
-void bs2b_cross_feed(struct bs2b *bs2b, float *restrict Left, float *restrict Right, int SamplesToDo)
+void bs2b_cross_feed(struct bs2b *bs2b, float *RESTRICT Left, float *RESTRICT Right, int SamplesToDo)
{
float lsamples[128][2];
float rsamples[128][2];
diff --git a/Alc/compat.h b/Alc/compat.h
index 495bfdf2..1c348c34 100644
--- a/Alc/compat.h
+++ b/Alc/compat.h
@@ -19,14 +19,213 @@ FILE *al_fopen(const char *fname, const char *mode);
#define HAVE_DYNLOAD 1
+#ifdef __cplusplus
+} // extern "C"
+
+#include <array>
+#include <string>
+#include <fstream>
+
+inline std::string wstr_to_utf8(const WCHAR *wstr)
+{
+ std::string ret;
+
+ int len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
+ if(len > 0)
+ {
+ ret.resize(len);
+ WideCharToMultiByte(CP_UTF8, 0, wstr, -1, &ret[0], len, nullptr, nullptr);
+ ret.pop_back();
+ }
+
+ return ret;
+}
+
+inline std::wstring utf8_to_wstr(const char *str)
+{
+ std::wstring ret;
+
+ int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+ if(len > 0)
+ {
+ ret.resize(len);
+ MultiByteToWideChar(CP_UTF8, 0, str, -1, &ret[0], len);
+ ret.pop_back();
+ }
+
+ return ret;
+}
+
+
+namespace al {
+
+// Windows' std::ifstream fails with non-ANSI paths since the standard only
+// specifies names using const char* (or std::string). MSVC has a non-standard
+// extension using const wchar_t* (or std::wstring?) to handle Unicode paths,
+// but not all Windows compilers support it. So we have to make our own istream
+// that accepts UTF-8 paths and forwards to Unicode-aware I/O functions.
+class filebuf final : public std::streambuf {
+ std::array<char_type,4096> mBuffer;
+ HANDLE mFile{INVALID_HANDLE_VALUE};
+
+ int_type underflow() override
+ {
+ if(mFile != INVALID_HANDLE_VALUE && gptr() == egptr())
+ {
+ // Read in the next chunk of data, and set the pointers on success
+ DWORD got = 0;
+ if(ReadFile(mFile, mBuffer.data(), (DWORD)mBuffer.size(), &got, nullptr))
+ setg(mBuffer.data(), mBuffer.data(), mBuffer.data()+got);
+ }
+ if(gptr() == egptr())
+ return traits_type::eof();
+ return traits_type::to_int_type(*gptr());
+ }
+
+ pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode) override
+ {
+ if(mFile == INVALID_HANDLE_VALUE || (mode&std::ios_base::out) || !(mode&std::ios_base::in))
+ return traits_type::eof();
+
+ LARGE_INTEGER fpos;
+ switch(whence)
+ {
+ case std::ios_base::beg:
+ fpos.QuadPart = offset;
+ if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_BEGIN))
+ return traits_type::eof();
+ break;
+
+ case std::ios_base::cur:
+ // If the offset remains in the current buffer range, just
+ // update the pointer.
+ if((offset >= 0 && offset < off_type(egptr()-gptr())) ||
+ (offset < 0 && -offset <= off_type(gptr()-eback())))
+ {
+ // Get the current file offset to report the correct read
+ // offset.
+ fpos.QuadPart = 0;
+ if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_CURRENT))
+ return traits_type::eof();
+ setg(eback(), gptr()+offset, egptr());
+ return fpos.QuadPart - off_type(egptr()-gptr());
+ }
+ // Need to offset for the file offset being at egptr() while
+ // the requested offset is relative to gptr().
+ offset -= off_type(egptr()-gptr());
+ fpos.QuadPart = offset;
+ if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_CURRENT))
+ return traits_type::eof();
+ break;
+
+ case std::ios_base::end:
+ fpos.QuadPart = offset;
+ if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_END))
+ return traits_type::eof();
+ break;
+
+ default:
+ return traits_type::eof();
+ }
+ setg(nullptr, nullptr, nullptr);
+ return fpos.QuadPart;
+ }
+
+ pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override
+ {
+ // Simplified version of seekoff
+ if(mFile == INVALID_HANDLE_VALUE || (mode&std::ios_base::out) || !(mode&std::ios_base::in))
+ return traits_type::eof();
+
+ LARGE_INTEGER fpos;
+ fpos.QuadPart = pos;
+ if(!SetFilePointerEx(mFile, fpos, &fpos, FILE_BEGIN))
+ return traits_type::eof();
+
+ setg(nullptr, nullptr, nullptr);
+ return fpos.QuadPart;
+ }
+
+public:
+ bool open(const wchar_t *filename)
+ {
+ mFile = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, nullptr,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if(mFile == INVALID_HANDLE_VALUE) return false;
+ return true;
+ }
+ bool open(const char *filename)
+ {
+ std::wstring wname{utf8_to_wstr(filename)};
+ return open(wname.c_str());
+ }
+
+ bool is_open() const noexcept { return mFile != INVALID_HANDLE_VALUE; }
+
+ filebuf() = default;
+ ~filebuf() override
+ {
+ if(mFile != INVALID_HANDLE_VALUE)
+ CloseHandle(mFile);
+ mFile = INVALID_HANDLE_VALUE;
+ }
+};
+
+// Inherit from std::istream to use our custom streambuf
+class ifstream final : public std::istream {
+ filebuf mStreamBuf;
+
+public:
+ ifstream(const std::wstring &filename) : ifstream{filename.c_str()} { }
+ ifstream(const wchar_t *filename) : std::istream{nullptr}
+ {
+ init(&mStreamBuf);
+
+ // Set the failbit if the file failed to open.
+ if(!mStreamBuf.open(filename)) clear(failbit);
+ }
+
+ ifstream(const std::string &filename) : ifstream{filename.c_str()} { }
+ ifstream(const char *filename) : std::istream{nullptr}
+ {
+ init(&mStreamBuf);
+
+ // Set the failbit if the file failed to open.
+ if(!mStreamBuf.open(filename)) clear(failbit);
+ }
+
+ bool is_open() const noexcept { return mStreamBuf.is_open(); }
+};
+
+} // namespace al
+
+extern "C" {
+#endif /* __cplusplus */
+
#else
#define al_fopen fopen
-#if defined(HAVE_DLFCN_H) && !defined(IN_IDE_PARSER)
+#if defined(HAVE_DLFCN_H)
#define HAVE_DYNLOAD 1
#endif
+
+#ifdef __cplusplus
+} // extern "C"
+
+#include <fstream>
+
+namespace al {
+
+using filebuf = std::filebuf;
+using ifstream = std::ifstream;
+
+} // namespace al
+
+extern "C" {
+#endif /* __cplusplus */
+
#endif
struct FileMapping {
diff --git a/Alc/converter.c b/Alc/converter.c
index ef2eb9af..5080f302 100644
--- a/Alc/converter.c
+++ b/Alc/converter.c
@@ -72,7 +72,7 @@ static inline ALfloat Sample_ALfloat(ALfloat val)
{ return val; }
#define DECL_TEMPLATE(T) \
-static inline void Load_##T(ALfloat *restrict dst, const T *restrict src, \
+static inline void Load_##T(ALfloat *RESTRICT dst, const T *RESTRICT src, \
ALint srcstep, ALsizei samples) \
{ \
ALsizei i; \
@@ -138,7 +138,7 @@ static inline ALfloat ALfloat_Sample(ALfloat val)
{ return val; }
#define DECL_TEMPLATE(T) \
-static inline void Store_##T(T *restrict dst, const ALfloat *restrict src, \
+static inline void Store_##T(T *RESTRICT dst, const ALfloat *RESTRICT src, \
ALint dststep, ALsizei samples) \
{ \
ALsizei i; \
@@ -235,8 +235,8 @@ ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALs
START_MIXER_MODE();
while(pos < dstframes && *srcframes > 0)
{
- ALfloat *restrict SrcData = ASSUME_ALIGNED(converter->mSrcSamples, 16);
- ALfloat *restrict DstData = ASSUME_ALIGNED(converter->mDstSamples, 16);
+ ALfloat *RESTRICT SrcData = ASSUME_ALIGNED(converter->mSrcSamples, 16);
+ ALfloat *RESTRICT DstData = ASSUME_ALIGNED(converter->mDstSamples, 16);
ALint prepcount = converter->mSrcPrepCount;
ALsizei DataPosFrac = converter->mFracOffset;
ALuint64 DataSize64;
@@ -377,14 +377,14 @@ void DestroyChannelConverter(ChannelConverter **converter)
#define DECL_TEMPLATE(T) \
-static void Mono2Stereo##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
+static void Mono2Stereo##T(ALfloat *RESTRICT dst, const T *src, ALsizei frames)\
{ \
ALsizei i; \
for(i = 0;i < frames;i++) \
dst[i*2 + 1] = dst[i*2 + 0] = Sample_##T(src[i]) * 0.707106781187f; \
} \
\
-static void Stereo2Mono##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
+static void Stereo2Mono##T(ALfloat *RESTRICT dst, const T *src, ALsizei frames)\
{ \
ALsizei i; \
for(i = 0;i < frames;i++) \
diff --git a/Alc/converter.h b/Alc/converter.h
index b58fd831..3f0c6304 100644
--- a/Alc/converter.h
+++ b/Alc/converter.h
@@ -4,7 +4,7 @@
#include "alMain.h"
#include "alu.h"
-#ifdef __cpluspluc
+#ifdef __cplusplus
extern "C" {
#endif
@@ -48,7 +48,7 @@ void DestroyChannelConverter(ChannelConverter **converter);
void ChannelConverterInput(ChannelConverter *converter, const ALvoid *src, ALfloat *dst, ALsizei frames);
-#ifdef __cpluspluc
+#ifdef __cplusplus
}
#endif
diff --git a/Alc/effects/autowah.c b/Alc/effects/autowah.c
index ba1180ef..f65f1be6 100644
--- a/Alc/effects/autowah.c
+++ b/Alc/effects/autowah.c
@@ -69,7 +69,7 @@ typedef struct ALautowahState {
static ALvoid ALautowahState_Destruct(ALautowahState *state);
static ALboolean ALautowahState_deviceUpdate(ALautowahState *state, ALCdevice *device);
static ALvoid ALautowahState_update(ALautowahState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALautowahState_process(ALautowahState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALautowahState_process(ALautowahState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALautowahState)
DEFINE_ALEFFECTSTATE_VTABLE(ALautowahState);
@@ -134,7 +134,7 @@ static ALvoid ALautowahState_update(ALautowahState *state, const ALCcontext *con
state->Chans[i].TargetGains);
}
-static ALvoid ALautowahState_process(ALautowahState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALautowahState_process(ALautowahState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
const ALfloat attack_rate = state->AttackRate;
const ALfloat release_rate = state->ReleaseRate;
diff --git a/Alc/effects/chorus.c b/Alc/effects/chorus.c
index f2861cf5..725189b3 100644
--- a/Alc/effects/chorus.c
+++ b/Alc/effects/chorus.c
@@ -66,7 +66,7 @@ typedef struct ALchorusState {
static ALvoid ALchorusState_Destruct(ALchorusState *state);
static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Device);
static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Context, const ALeffectslot *Slot, const ALeffectProps *props);
-static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALchorusState)
DEFINE_ALEFFECTSTATE_VTABLE(ALchorusState);
@@ -188,7 +188,7 @@ static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Conte
}
}
-static void GetTriangleDelays(ALint *restrict delays, ALsizei offset, const ALsizei lfo_range,
+static void GetTriangleDelays(ALint *RESTRICT delays, ALsizei offset, const ALsizei lfo_range,
const ALfloat lfo_scale, const ALfloat depth, const ALsizei delay,
const ALsizei todo)
{
@@ -200,7 +200,7 @@ static void GetTriangleDelays(ALint *restrict delays, ALsizei offset, const ALsi
}
}
-static void GetSinusoidDelays(ALint *restrict delays, ALsizei offset, const ALsizei lfo_range,
+static void GetSinusoidDelays(ALint *RESTRICT delays, ALsizei offset, const ALsizei lfo_range,
const ALfloat lfo_scale, const ALfloat depth, const ALsizei delay,
const ALsizei todo)
{
@@ -213,12 +213,12 @@ static void GetSinusoidDelays(ALint *restrict delays, ALsizei offset, const ALsi
}
-static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
const ALsizei bufmask = state->BufferLength-1;
const ALfloat feedback = state->feedback;
const ALsizei avgdelay = (state->delay + (FRACTIONONE>>1)) >> FRACTIONBITS;
- ALfloat *restrict delaybuf = state->SampleBuffer;
+ ALfloat *RESTRICT delaybuf = state->SampleBuffer;
ALsizei offset = state->offset;
ALsizei i, c;
ALsizei base;
diff --git a/Alc/effects/compressor.c b/Alc/effects/compressor.c
index 2b4a76b0..d9b9f1e0 100644
--- a/Alc/effects/compressor.c
+++ b/Alc/effects/compressor.c
@@ -50,7 +50,7 @@ typedef struct ALcompressorState {
static ALvoid ALcompressorState_Destruct(ALcompressorState *state);
static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdevice *device);
static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALcompressorState_process(ALcompressorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALcompressorState_process(ALcompressorState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALcompressorState)
DEFINE_ALEFFECTSTATE_VTABLE(ALcompressorState);
@@ -102,7 +102,7 @@ static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCcontex
ComputePanGains(&device->FOAOut, IdentityMatrixf.m[i], slot->Params.Gain, state->Gain[i]);
}
-static ALvoid ALcompressorState_process(ALcompressorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALcompressorState_process(ALcompressorState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
ALsizei i, j, k;
ALsizei base;
diff --git a/Alc/effects/dedicated.c b/Alc/effects/dedicated.c
index 0e1fd389..59c13b77 100644
--- a/Alc/effects/dedicated.c
+++ b/Alc/effects/dedicated.c
@@ -39,7 +39,7 @@ typedef struct ALdedicatedState {
static ALvoid ALdedicatedState_Destruct(ALdedicatedState *state);
static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *state, ALCdevice *device);
static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALdedicatedState)
DEFINE_ALEFFECTSTATE_VTABLE(ALdedicatedState);
@@ -107,7 +107,7 @@ static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCcontext
}
}
-static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
MixSamples(SamplesIn[0], NumChannels, SamplesOut, state->CurrentGains,
state->TargetGains, SamplesToDo, 0, SamplesToDo);
diff --git a/Alc/effects/distortion.c b/Alc/effects/distortion.c
index de8da4fe..f2a70bff 100644
--- a/Alc/effects/distortion.c
+++ b/Alc/effects/distortion.c
@@ -48,7 +48,7 @@ typedef struct ALdistortionState {
static ALvoid ALdistortionState_Destruct(ALdistortionState *state);
static ALboolean ALdistortionState_deviceUpdate(ALdistortionState *state, ALCdevice *device);
static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALdistortionState_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALdistortionState_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALdistortionState)
DEFINE_ALEFFECTSTATE_VTABLE(ALdistortionState);
@@ -107,9 +107,9 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCcontex
ComputePanGains(&device->Dry, coeffs, slot->Params.Gain*props->Distortion.Gain, state->Gain);
}
-static ALvoid ALdistortionState_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALdistortionState_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
- ALfloat (*restrict buffer)[BUFFERSIZE] = state->Buffer;
+ ALfloat (*RESTRICT buffer)[BUFFERSIZE] = state->Buffer;
const ALfloat fc = state->edge_coeff;
ALsizei base;
ALsizei i, k;
diff --git a/Alc/effects/echo.c b/Alc/effects/echo.c
index 4570fcb1..5c323986 100644
--- a/Alc/effects/echo.c
+++ b/Alc/effects/echo.c
@@ -58,7 +58,7 @@ typedef struct ALechoState {
static ALvoid ALechoState_Destruct(ALechoState *state);
static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device);
static ALvoid ALechoState_update(ALechoState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALechoState)
DEFINE_ALEFFECTSTATE_VTABLE(ALechoState);
@@ -148,12 +148,12 @@ static ALvoid ALechoState_update(ALechoState *state, const ALCcontext *context,
ComputePanGains(&device->Dry, coeffs, slot->Params.Gain, state->Gains[1].Target);
}
-static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
const ALsizei mask = state->BufferLength-1;
const ALsizei tap1 = state->Tap[0].delay;
const ALsizei tap2 = state->Tap[1].delay;
- ALfloat *restrict delaybuf = state->SampleBuffer;
+ ALfloat *RESTRICT delaybuf = state->SampleBuffer;
ALsizei offset = state->Offset;
ALfloat z1, z2, in, out;
ALsizei base;
diff --git a/Alc/effects/equalizer.c b/Alc/effects/equalizer.c
index 17106127..c62f8e80 100644
--- a/Alc/effects/equalizer.c
+++ b/Alc/effects/equalizer.c
@@ -90,7 +90,7 @@ typedef struct ALequalizerState {
static ALvoid ALequalizerState_Destruct(ALequalizerState *state);
static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *state, ALCdevice *device);
static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALequalizerState_process(ALequalizerState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALequalizerState_process(ALequalizerState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALequalizerState)
DEFINE_ALEFFECTSTATE_VTABLE(ALequalizerState);
@@ -176,9 +176,9 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCcontext
state->Chans[i].TargetGains);
}
-static ALvoid ALequalizerState_process(ALequalizerState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALequalizerState_process(ALequalizerState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
- ALfloat (*restrict temps)[BUFFERSIZE] = state->SampleBuffer;
+ ALfloat (*RESTRICT temps)[BUFFERSIZE] = state->SampleBuffer;
ALsizei c;
for(c = 0;c < MAX_EFFECT_CHANNELS;c++)
diff --git a/Alc/effects/fshifter.c b/Alc/effects/fshifter.c
index 7d72472a..6ada7dfa 100644
--- a/Alc/effects/fshifter.c
+++ b/Alc/effects/fshifter.c
@@ -64,7 +64,7 @@ typedef struct ALfshifterState {
static ALvoid ALfshifterState_Destruct(ALfshifterState *state);
static ALboolean ALfshifterState_deviceUpdate(ALfshifterState *state, ALCdevice *device);
static ALvoid ALfshifterState_update(ALfshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALfshifterState_process(ALfshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALfshifterState_process(ALfshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALfshifterState)
DEFINE_ALEFFECTSTATE_VTABLE(ALfshifterState);
@@ -147,10 +147,10 @@ static ALvoid ALfshifterState_update(ALfshifterState *state, const ALCcontext *c
ComputePanGains(&device->Dry, coeffs, slot->Params.Gain, state->TargetGains);
}
-static ALvoid ALfshifterState_process(ALfshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALfshifterState_process(ALfshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
static const ALcomplex complex_zero = { 0.0, 0.0 };
- ALfloat *restrict BufferOut = state->BufferOut;
+ ALfloat *RESTRICT BufferOut = state->BufferOut;
ALsizei j, k, base;
for(base = 0;base < SamplesToDo;)
diff --git a/Alc/effects/modulator.c b/Alc/effects/modulator.c
index e368adb8..87799dd7 100644
--- a/Alc/effects/modulator.c
+++ b/Alc/effects/modulator.c
@@ -35,7 +35,7 @@
typedef struct ALmodulatorState {
DERIVE_FROM_TYPE(ALeffectState);
- void (*GetSamples)(ALfloat*, ALsizei, const ALsizei, ALsizei);
+ void (*GetSamples)(ALfloat*RESTRICT, ALsizei, const ALsizei, ALsizei);
ALsizei index;
ALsizei step;
@@ -51,7 +51,7 @@ typedef struct ALmodulatorState {
static ALvoid ALmodulatorState_Destruct(ALmodulatorState *state);
static ALboolean ALmodulatorState_deviceUpdate(ALmodulatorState *state, ALCdevice *device);
static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState)
DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState);
@@ -82,7 +82,7 @@ static inline ALfloat One(ALsizei UNUSED(index))
}
#define DECL_TEMPLATE(func) \
-static void Modulate##func(ALfloat *restrict dst, ALsizei index, \
+static void Modulate##func(ALfloat *RESTRICT dst, ALsizei index, \
const ALsizei step, ALsizei todo) \
{ \
ALsizei i; \
@@ -162,7 +162,7 @@ static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCcontext
state->Chans[i].TargetGains);
}
-static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
const ALsizei step = state->step;
ALsizei base;
diff --git a/Alc/effects/null.c b/Alc/effects/null.c
index e57359e3..82ea5d26 100644
--- a/Alc/effects/null.c
+++ b/Alc/effects/null.c
@@ -17,7 +17,7 @@ typedef struct ALnullState {
static ALvoid ALnullState_Destruct(ALnullState *state);
static ALboolean ALnullState_deviceUpdate(ALnullState *state, ALCdevice *device);
static ALvoid ALnullState_update(ALnullState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALnullState_process(ALnullState *state, ALsizei samplesToDo, const ALfloat (*restrict samplesIn)[BUFFERSIZE], ALfloat (*restrict samplesOut)[BUFFERSIZE], ALsizei mumChannels);
+static ALvoid ALnullState_process(ALnullState *state, ALsizei samplesToDo, const ALfloat (*RESTRICT samplesIn)[BUFFERSIZE], ALfloat (*RESTRICT samplesOut)[BUFFERSIZE], ALsizei mumChannels);
static void *ALnullState_New(size_t size);
static void ALnullState_Delete(void *ptr);
@@ -64,7 +64,7 @@ static ALvoid ALnullState_update(ALnullState* UNUSED(state), const ALCcontext* U
* input to the output buffer. The result should be added to the output buffer,
* not replace it.
*/
-static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALsizei UNUSED(samplesToDo), const ALfloatBUFFERSIZE*restrict UNUSED(samplesIn), ALfloatBUFFERSIZE*restrict UNUSED(samplesOut), ALsizei UNUSED(numChannels))
+static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALsizei UNUSED(samplesToDo), const ALfloatBUFFERSIZE*RESTRICT UNUSED(samplesIn), ALfloatBUFFERSIZE*RESTRICT UNUSED(samplesOut), ALsizei UNUSED(numChannels))
{
}
@@ -73,7 +73,7 @@ static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALsizei UNUSED(sam
*/
static void *ALnullState_New(size_t size)
{
- return al_malloc(16, size);
+ return al_calloc(16, size);
}
/* This frees the memory used by the object, after it has been destructed.
diff --git a/Alc/effects/pshifter.c b/Alc/effects/pshifter.c
index ed18e9a8..35168eab 100644
--- a/Alc/effects/pshifter.c
+++ b/Alc/effects/pshifter.c
@@ -82,7 +82,7 @@ typedef struct ALpshifterState {
static ALvoid ALpshifterState_Destruct(ALpshifterState *state);
static ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device);
static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ALpshifterState)
DEFINE_ALEFFECTSTATE_VTABLE(ALpshifterState);
@@ -211,7 +211,7 @@ static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *c
ComputePanGains(&device->Dry, coeffs, slot->Params.Gain, state->TargetGains);
}
-static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
/* Pitch shifter engine based on the work of Stephan Bernsee.
* http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/
@@ -219,7 +219,7 @@ static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToD
static const ALdouble expected = M_PI*2.0 / OVERSAMP;
const ALdouble freq_per_bin = state->FreqPerBin;
- ALfloat *restrict bufferOut = state->BufferOut;
+ ALfloat *RESTRICT bufferOut = state->BufferOut;
ALsizei count = state->count;
ALsizei i, j, k;
diff --git a/Alc/effects/reverb.c b/Alc/effects/reverb.c
index 8ebc089e..ad4aae5c 100644
--- a/Alc/effects/reverb.c
+++ b/Alc/effects/reverb.c
@@ -334,7 +334,7 @@ typedef struct ReverbState {
static ALvoid ReverbState_Destruct(ReverbState *State);
static ALboolean ReverbState_deviceUpdate(ReverbState *State, ALCdevice *Device);
static ALvoid ReverbState_update(ReverbState *State, const ALCcontext *Context, const ALeffectslot *Slot, const ALeffectProps *props);
-static ALvoid ReverbState_process(ReverbState *State, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+static ALvoid ReverbState_process(ReverbState *State, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
DECLARE_DEFAULT_ALLOCATORS(ReverbState)
DEFINE_ALEFFECTSTATE_VTABLE(ReverbState);
@@ -1069,7 +1069,7 @@ static inline ALfloat FadedDelayLineOut(const DelayLineI *Delay, const ALsizei o
static inline void DelayLineIn(const DelayLineI *Delay, ALsizei offset, const ALsizei c,
- const ALfloat *restrict in, ALsizei count)
+ const ALfloat *RESTRICT in, ALsizei count)
{
ALsizei i;
for(i = 0;i < count;i++)
@@ -1114,7 +1114,7 @@ static inline void DelayLineIn(const DelayLineI *Delay, ALsizei offset, const AL
* Where D is a diagonal matrix (of x), and S is a triangular matrix (of y)
* whose combination of signs are being iterated.
*/
-static inline void VectorPartialScatter(ALfloat *restrict out, const ALfloat *restrict in,
+static inline void VectorPartialScatter(ALfloat *RESTRICT out, const ALfloat *RESTRICT in,
const ALfloat xCoeff, const ALfloat yCoeff)
{
out[0] = xCoeff*in[0] + yCoeff*( in[1] + -in[2] + in[3]);
@@ -1128,7 +1128,7 @@ static inline void VectorPartialScatter(ALfloat *restrict out, const ALfloat *re
/* Utilizes the above, but reverses the input channels. */
static inline void VectorScatterRevDelayIn(const DelayLineI *Delay, ALint offset,
const ALfloat xCoeff, const ALfloat yCoeff,
- const ALfloat (*restrict in)[MAX_UPDATE_SAMPLES],
+ const ALfloat (*RESTRICT in)[MAX_UPDATE_SAMPLES],
const ALsizei count)
{
const DelayLineI delay = *Delay;
@@ -1154,7 +1154,7 @@ static inline void VectorScatterRevDelayIn(const DelayLineI *Delay, ALint offset
* Two static specializations are used for transitional (cross-faded) delay
* line processing and non-transitional processing.
*/
-static void VectorAllpass_Unfaded(ALfloat (*restrict samples)[MAX_UPDATE_SAMPLES], ALsizei offset,
+static void VectorAllpass_Unfaded(ALfloat (*RESTRICT samples)[MAX_UPDATE_SAMPLES], ALsizei offset,
const ALfloat xCoeff, const ALfloat yCoeff, ALsizei todo,
VecAllpass *Vap)
{
@@ -1184,7 +1184,7 @@ static void VectorAllpass_Unfaded(ALfloat (*restrict samples)[MAX_UPDATE_SAMPLES
++offset;
}
}
-static void VectorAllpass_Faded(ALfloat (*restrict samples)[MAX_UPDATE_SAMPLES], ALsizei offset,
+static void VectorAllpass_Faded(ALfloat (*RESTRICT samples)[MAX_UPDATE_SAMPLES], ALsizei offset,
const ALfloat xCoeff, const ALfloat yCoeff, ALfloat fade,
ALsizei todo, VecAllpass *Vap)
{
@@ -1243,9 +1243,9 @@ static void VectorAllpass_Faded(ALfloat (*restrict samples)[MAX_UPDATE_SAMPLES],
* line processing and non-transitional processing.
*/
static void EarlyReflection_Unfaded(ReverbState *State, ALsizei offset, const ALsizei todo,
- ALfloat (*restrict out)[MAX_UPDATE_SAMPLES])
+ ALfloat (*RESTRICT out)[MAX_UPDATE_SAMPLES])
{
- ALfloat (*restrict temps)[MAX_UPDATE_SAMPLES] = State->TempSamples;
+ ALfloat (*RESTRICT temps)[MAX_UPDATE_SAMPLES] = State->TempSamples;
const DelayLineI early_delay = State->Early.Delay;
const DelayLineI main_delay = State->Delay;
const ALfloat mixX = State->MixX;
@@ -1294,9 +1294,9 @@ static void EarlyReflection_Unfaded(ReverbState *State, ALsizei offset, const AL
VectorScatterRevDelayIn(&main_delay, late_feed_tap, mixX, mixY, out, todo);
}
static void EarlyReflection_Faded(ReverbState *State, ALsizei offset, const ALsizei todo,
- const ALfloat fade, ALfloat (*restrict out)[MAX_UPDATE_SAMPLES])
+ const ALfloat fade, ALfloat (*RESTRICT out)[MAX_UPDATE_SAMPLES])
{
- ALfloat (*restrict temps)[MAX_UPDATE_SAMPLES] = State->TempSamples;
+ ALfloat (*RESTRICT temps)[MAX_UPDATE_SAMPLES] = State->TempSamples;
const DelayLineI early_delay = State->Early.Delay;
const DelayLineI main_delay = State->Delay;
const ALfloat mixX = State->MixX;
@@ -1355,7 +1355,7 @@ static void EarlyReflection_Faded(ReverbState *State, ALsizei offset, const ALsi
}
/* Applies the two T60 damping filter sections. */
-static inline void LateT60Filter(ALfloat *restrict samples, const ALsizei todo, T60Filter *filter)
+static inline void LateT60Filter(ALfloat *RESTRICT samples, const ALsizei todo, T60Filter *filter)
{
ALfloat temp[MAX_UPDATE_SAMPLES];
BiquadFilter_process(&filter->HFFilter, temp, samples, todo);
@@ -1377,9 +1377,9 @@ static inline void LateT60Filter(ALfloat *restrict samples, const ALsizei todo,
* processing and one for non-transitional processing.
*/
static void LateReverb_Unfaded(ReverbState *State, ALsizei offset, const ALsizei todo,
- ALfloat (*restrict out)[MAX_UPDATE_SAMPLES])
+ ALfloat (*RESTRICT out)[MAX_UPDATE_SAMPLES])
{
- ALfloat (*restrict temps)[MAX_UPDATE_SAMPLES] = State->TempSamples;
+ ALfloat (*RESTRICT temps)[MAX_UPDATE_SAMPLES] = State->TempSamples;
const DelayLineI late_delay = State->Late.Delay;
const DelayLineI main_delay = State->Delay;
const ALfloat mixX = State->MixX;
@@ -1415,9 +1415,9 @@ static void LateReverb_Unfaded(ReverbState *State, ALsizei offset, const ALsizei
VectorScatterRevDelayIn(&late_delay, offset, mixX, mixY, out, todo);
}
static void LateReverb_Faded(ReverbState *State, ALsizei offset, const ALsizei todo,
- const ALfloat fade, ALfloat (*restrict out)[MAX_UPDATE_SAMPLES])
+ const ALfloat fade, ALfloat (*RESTRICT out)[MAX_UPDATE_SAMPLES])
{
- ALfloat (*restrict temps)[MAX_UPDATE_SAMPLES] = State->TempSamples;
+ ALfloat (*RESTRICT temps)[MAX_UPDATE_SAMPLES] = State->TempSamples;
const DelayLineI late_delay = State->Late.Delay;
const DelayLineI main_delay = State->Delay;
const ALfloat mixX = State->MixX;
@@ -1466,10 +1466,10 @@ static void LateReverb_Faded(ReverbState *State, ALsizei offset, const ALsizei t
VectorScatterRevDelayIn(&late_delay, offset, mixX, mixY, temps, todo);
}
-static ALvoid ReverbState_process(ReverbState *State, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+static ALvoid ReverbState_process(ReverbState *State, ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
{
- ALfloat (*restrict afmt)[MAX_UPDATE_SAMPLES] = State->TempSamples;
- ALfloat (*restrict samples)[MAX_UPDATE_SAMPLES] = State->MixSamples;
+ ALfloat (*RESTRICT afmt)[MAX_UPDATE_SAMPLES] = State->TempSamples;
+ ALfloat (*RESTRICT samples)[MAX_UPDATE_SAMPLES] = State->MixSamples;
ALsizei fadeCount = State->FadeCount;
ALsizei offset = State->Offset;
ALsizei base, c;
diff --git a/Alc/filters/defs.h b/Alc/filters/defs.h
index 133a85eb..beb4ab3e 100644
--- a/Alc/filters/defs.h
+++ b/Alc/filters/defs.h
@@ -84,7 +84,7 @@ inline void BiquadFilter_clear(BiquadFilter *filter)
*/
void BiquadFilter_setParams(BiquadFilter *filter, BiquadType type, ALfloat gain, ALfloat f0norm, ALfloat rcpQ);
-inline void BiquadFilter_copyParams(BiquadFilter *restrict dst, const BiquadFilter *restrict src)
+inline void BiquadFilter_copyParams(BiquadFilter *RESTRICT dst, const BiquadFilter *RESTRICT src)
{
dst->b0 = src->b0;
dst->b1 = src->b1;
@@ -93,7 +93,7 @@ inline void BiquadFilter_copyParams(BiquadFilter *restrict dst, const BiquadFilt
dst->a2 = src->a2;
}
-void BiquadFilter_processC(BiquadFilter *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALsizei numsamples);
+void BiquadFilter_processC(BiquadFilter *filter, ALfloat *RESTRICT dst, const ALfloat *RESTRICT src, ALsizei numsamples);
inline void BiquadFilter_passthru(BiquadFilter *filter, ALsizei numsamples)
{
diff --git a/Alc/filters/filter.c b/Alc/filters/filter.c
index 2b370f89..d05b0cae 100644
--- a/Alc/filters/filter.c
+++ b/Alc/filters/filter.c
@@ -8,7 +8,7 @@
#include "defs.h"
extern inline void BiquadFilter_clear(BiquadFilter *filter);
-extern inline void BiquadFilter_copyParams(BiquadFilter *restrict dst, const BiquadFilter *restrict src);
+extern inline void BiquadFilter_copyParams(BiquadFilter *RESTRICT dst, const BiquadFilter *RESTRICT src);
extern inline void BiquadFilter_passthru(BiquadFilter *filter, ALsizei numsamples);
extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope);
extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat f0norm, ALfloat bandwidth);
@@ -94,7 +94,7 @@ void BiquadFilter_setParams(BiquadFilter *filter, BiquadType type, ALfloat gain,
}
-void BiquadFilter_processC(BiquadFilter *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALsizei numsamples)
+void BiquadFilter_processC(BiquadFilter *filter, ALfloat *RESTRICT dst, const ALfloat *RESTRICT src, ALsizei numsamples)
{
const ALfloat a1 = filter->a1;
const ALfloat a2 = filter->a2;
diff --git a/Alc/filters/nfc.c b/Alc/filters/nfc.c
index 8869d1d0..8d61bb37 100644
--- a/Alc/filters/nfc.c
+++ b/Alc/filters/nfc.c
@@ -222,7 +222,7 @@ void NfcFilterAdjust(NfcFilter *nfc, const float w0)
}
-void NfcFilterProcess1(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count)
+void NfcFilterProcess1(NfcFilter *nfc, float *RESTRICT dst, const float *RESTRICT src, const int count)
{
const float gain = nfc->first.gain;
const float b1 = nfc->first.b1;
@@ -243,7 +243,7 @@ void NfcFilterProcess1(NfcFilter *nfc, float *restrict dst, const float *restric
nfc->first.z[0] = z1;
}
-void NfcFilterProcess2(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count)
+void NfcFilterProcess2(NfcFilter *nfc, float *RESTRICT dst, const float *RESTRICT src, const int count)
{
const float gain = nfc->second.gain;
const float b1 = nfc->second.b1;
@@ -269,7 +269,7 @@ void NfcFilterProcess2(NfcFilter *nfc, float *restrict dst, const float *restric
nfc->second.z[1] = z2;
}
-void NfcFilterProcess3(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count)
+void NfcFilterProcess3(NfcFilter *nfc, float *RESTRICT dst, const float *RESTRICT src, const int count)
{
const float gain = nfc->third.gain;
const float b1 = nfc->third.b1;
diff --git a/Alc/filters/nfc.h b/Alc/filters/nfc.h
index 12a5a18f..e02c00d8 100644
--- a/Alc/filters/nfc.h
+++ b/Alc/filters/nfc.h
@@ -38,12 +38,12 @@ void NfcFilterCreate(NfcFilter *nfc, const float w0, const float w1);
void NfcFilterAdjust(NfcFilter *nfc, const float w0);
/* Near-field control filter for first-order ambisonic channels (1-3). */
-void NfcFilterProcess1(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
+void NfcFilterProcess1(NfcFilter *nfc, float *RESTRICT dst, const float *RESTRICT src, const int count);
/* Near-field control filter for second-order ambisonic channels (4-8). */
-void NfcFilterProcess2(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
+void NfcFilterProcess2(NfcFilter *nfc, float *RESTRICT dst, const float *RESTRICT src, const int count);
/* Near-field control filter for third-order ambisonic channels (9-15). */
-void NfcFilterProcess3(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
+void NfcFilterProcess3(NfcFilter *nfc, float *RESTRICT dst, const float *RESTRICT src, const int count);
#endif /* FILTER_NFC_H */
diff --git a/Alc/filters/splitter.c b/Alc/filters/splitter.cpp
index e99f4b95..6aed7493 100644
--- a/Alc/filters/splitter.c
+++ b/Alc/filters/splitter.cpp
@@ -27,7 +27,7 @@ void bandsplit_clear(BandSplitter *splitter)
splitter->hp_z1 = 0.0f;
}
-void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
+void bandsplit_process(BandSplitter *splitter, ALfloat *RESTRICT hpout, ALfloat *RESTRICT lpout,
const ALfloat *input, ALsizei count)
{
ALfloat lp_coeff, hp_coeff, lp_y, hp_y, d;
@@ -86,7 +86,7 @@ void splitterap_clear(SplitterAllpass *splitter)
splitter->z1 = 0.0f;
}
-void splitterap_process(SplitterAllpass *splitter, ALfloat *restrict samples, ALsizei count)
+void splitterap_process(SplitterAllpass *splitter, ALfloat *RESTRICT samples, ALsizei count)
{
ALfloat coeff, in, out;
ALfloat z1;
diff --git a/Alc/filters/splitter.h b/Alc/filters/splitter.h
index a788bc3e..a996917c 100644
--- a/Alc/filters/splitter.h
+++ b/Alc/filters/splitter.h
@@ -3,6 +3,9 @@
#include "alMain.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
/* Band splitter. Splits a signal into two phase-matching frequency bands. */
typedef struct BandSplitter {
@@ -14,7 +17,7 @@ typedef struct BandSplitter {
void bandsplit_init(BandSplitter *splitter, ALfloat f0norm);
void bandsplit_clear(BandSplitter *splitter);
-void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
+void bandsplit_process(BandSplitter *splitter, ALfloat *RESTRICT hpout, ALfloat *RESTRICT lpout,
const ALfloat *input, ALsizei count);
/* The all-pass portion of the band splitter. Applies the same phase shift
@@ -27,7 +30,7 @@ typedef struct SplitterAllpass {
void splitterap_init(SplitterAllpass *splitter, ALfloat f0norm);
void splitterap_clear(SplitterAllpass *splitter);
-void splitterap_process(SplitterAllpass *splitter, ALfloat *restrict samples, ALsizei count);
+void splitterap_process(SplitterAllpass *splitter, ALfloat *RESTRICT samples, ALsizei count);
typedef struct FrontStablizer {
@@ -37,4 +40,8 @@ typedef struct FrontStablizer {
alignas(16) ALfloat RSplit[2][BUFFERSIZE];
} FrontStablizer;
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* FILTER_SPLITTER_H */
diff --git a/Alc/helpers.c b/Alc/helpers.c
index d2cb6253..0d5087e6 100644
--- a/Alc/helpers.c
+++ b/Alc/helpers.c
@@ -842,7 +842,7 @@ static void DirectorySearch(const char *path, const char *ext, vector_al_string
continue;
len = strlen(dirent->d_name);
- if(!(len > extlen))
+ if(len <= extlen)
continue;
if(strcasecmp(dirent->d_name+len-extlen, ext) != 0)
continue;
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index ddbd3a28..ce602ee1 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -103,7 +103,7 @@ static ALsizei CalcAzIndex(ALsizei azcount, ALfloat az, ALfloat *mu)
* and azimuth in radians. The coefficients are normalized.
*/
void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread,
- ALfloat (*restrict coeffs)[2], ALsizei *delays)
+ ALfloat (*RESTRICT coeffs)[2], ALsizei *delays)
{
ALsizei evidx, azidx, idx[4];
ALsizei evoffset;
@@ -183,7 +183,7 @@ void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth,
}
for(c = 0;c < 4;c++)
{
- const ALfloat (*restrict srccoeffs)[2] = ASSUME_ALIGNED(Hrtf->coeffs+idx[c], 16);
+ const ALfloat (*RESTRICT srccoeffs)[2] = ASSUME_ALIGNED(Hrtf->coeffs+idx[c], 16);
for(i = 0;i < Hrtf->irSize;i++)
{
coeffs[i][0] += srccoeffs[i][0] * blend[c];
@@ -193,7 +193,7 @@ void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth,
}
-void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const struct AngularPoint *AmbiPoints, const ALfloat (*restrict AmbiMatrix)[MAX_AMBI_COEFFS], ALsizei AmbiCount, const ALfloat *restrict AmbiOrderHFGain)
+void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const struct AngularPoint *AmbiPoints, const ALfloat (*RESTRICT AmbiMatrix)[MAX_AMBI_COEFFS], ALsizei AmbiCount, const ALfloat *RESTRICT AmbiOrderHFGain)
{
/* Set this to 2 for dual-band HRTF processing. May require a higher quality
* band-splitter, or better calculation of the new IR length to deal with the
@@ -202,7 +202,7 @@ void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei N
#define NUM_BANDS 2
BandSplitter splitter;
ALdouble (*tmpres)[HRIR_LENGTH][2];
- ALsizei *restrict idx;
+ ALsizei *RESTRICT idx;
ALsizei min_delay = HRTF_HISTORY_LENGTH;
ALsizei max_delay = 0;
ALfloat temps[3][HRIR_LENGTH];
diff --git a/Alc/hrtf.h b/Alc/hrtf.h
index ab68929b..1cdfe568 100644
--- a/Alc/hrtf.h
+++ b/Alc/hrtf.h
@@ -9,6 +9,10 @@
#include "atomic.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define HRTF_HISTORY_BITS (6)
#define HRTF_HISTORY_LENGTH (1<<HRTF_HISTORY_BITS)
#define HRTF_HISTORY_MASK (HRTF_HISTORY_LENGTH-1)
@@ -71,7 +75,7 @@ struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry);
void Hrtf_IncRef(struct Hrtf *hrtf);
void Hrtf_DecRef(struct Hrtf *hrtf);
-void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat (*coeffs)[2], ALsizei *delays);
+void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat (*RESTRICT coeffs)[2], ALsizei *delays);
/**
* Produces HRTF filter coefficients for decoding B-Format, given a set of
@@ -79,6 +83,10 @@ void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth,
* frequency gains for the decoder. The calculated impulse responses are
* ordered and scaled according to the matrix input.
*/
-void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const struct AngularPoint *AmbiPoints, const ALfloat (*restrict AmbiMatrix)[MAX_AMBI_COEFFS], ALsizei AmbiCount, const ALfloat *restrict AmbiOrderHFGain);
+void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const struct AngularPoint *AmbiPoints, const ALfloat (*RESTRICT AmbiMatrix)[MAX_AMBI_COEFFS], ALsizei AmbiCount, const ALfloat *RESTRICT AmbiOrderHFGain);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
#endif /* ALC_HRTF_H */
diff --git a/Alc/logging.h b/Alc/logging.h
index 785771c8..2d9f4063 100644
--- a/Alc/logging.h
+++ b/Alc/logging.h
@@ -17,7 +17,7 @@ extern "C" {
extern FILE *LogFile;
#if defined(__GNUC__) && !defined(_WIN32)
-#define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: "MSG, T, __FUNCTION__ , ## __VA_ARGS__)
+#define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: " MSG, T, __FUNCTION__ , ## __VA_ARGS__)
#else
void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4);
#define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__)
@@ -25,7 +25,7 @@ void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FOR
#ifdef __ANDROID__
#include <android/log.h>
-#define LOG_ANDROID(T, MSG, ...) __android_log_print(T, "openal", "AL lib: %s: "MSG, __FUNCTION__ , ## __VA_ARGS__)
+#define LOG_ANDROID(T, MSG, ...) __android_log_print(T, "openal", "AL lib: %s: " MSG, __FUNCTION__ , ## __VA_ARGS__)
#else
#define LOG_ANDROID(T, MSG, ...) ((void)0)
#endif
diff --git a/Alc/mastering.c b/Alc/mastering.c
index 52ff5b23..5ccf3a9e 100644
--- a/Alc/mastering.c
+++ b/Alc/mastering.c
@@ -6,6 +6,19 @@
#include "alu.h"
#include "almalloc.h"
#include "static_assert.h"
+#include "math_defs.h"
+
+
+/* Early MSVC lacks round/roundf */
+#if defined(_MSC_VER) && _MSC_VER < 1800
+static double round(double val)
+{
+ if(val < 0.0)
+ return ceil(val-0.5);
+ return floor(val+0.5);
+}
+#define roundf(f) ((float)round((float)(f)))
+#endif
/* These structures assume BUFFERSIZE is a power of 2. */
@@ -83,8 +96,8 @@ static ALfloat UpdateSlidingHold(SlidingHold *Hold, const ALsizei i, const ALflo
{
const ALsizei mask = BUFFERSIZE - 1;
const ALsizei length = Hold->Length;
- ALfloat *restrict values = Hold->Values;
- ALsizei *restrict expiries = Hold->Expiries;
+ ALfloat *RESTRICT values = Hold->Values;
+ ALsizei *RESTRICT expiries = Hold->Expiries;
ALsizei lowerIndex = Hold->LowerIndex;
ALsizei upperIndex = Hold->UpperIndex;
@@ -122,7 +135,7 @@ static ALfloat UpdateSlidingHold(SlidingHold *Hold, const ALsizei i, const ALflo
static void ShiftSlidingHold(SlidingHold *Hold, const ALsizei n)
{
const ALsizei lowerIndex = Hold->LowerIndex;
- ALsizei *restrict expiries = Hold->Expiries;
+ ALsizei *RESTRICT expiries = Hold->Expiries;
ALsizei i = Hold->UpperIndex;
if(lowerIndex < i)
@@ -140,11 +153,11 @@ static void ShiftSlidingHold(SlidingHold *Hold, const ALsizei n)
/* Multichannel compression is linked via the absolute maximum of all
* channels.
*/
-static void LinkChannels(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*restrict OutBuffer)[BUFFERSIZE])
+static void LinkChannels(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE])
{
const ALsizei index = Comp->LookAhead;
const ALsizei numChans = Comp->NumChans;
- ALfloat *restrict sideChain = Comp->SideChain;
+ ALfloat *RESTRICT sideChain = Comp->SideChain;
ALsizei c, i;
ASSUME(SamplesToDo > 0);
@@ -173,8 +186,8 @@ static void CrestDetector(Compressor *Comp, const ALsizei SamplesToDo)
{
const ALfloat a_crest = Comp->CrestCoeff;
const ALsizei index = Comp->LookAhead;
- const ALfloat *restrict sideChain = Comp->SideChain;
- ALfloat *restrict crestFactor = Comp->CrestFactor;
+ const ALfloat *RESTRICT sideChain = Comp->SideChain;
+ ALfloat *RESTRICT crestFactor = Comp->CrestFactor;
ALfloat y2_peak = Comp->LastPeakSq;
ALfloat y2_rms = Comp->LastRmsSq;
ALsizei i;
@@ -202,7 +215,7 @@ static void CrestDetector(Compressor *Comp, const ALsizei SamplesToDo)
static void PeakDetector(Compressor *Comp, const ALsizei SamplesToDo)
{
const ALsizei index = Comp->LookAhead;
- ALfloat *restrict sideChain = Comp->SideChain;
+ ALfloat *RESTRICT sideChain = Comp->SideChain;
ALsizei i;
ASSUME(SamplesToDo > 0);
@@ -223,7 +236,7 @@ static void PeakDetector(Compressor *Comp, const ALsizei SamplesToDo)
static void PeakHoldDetector(Compressor *Comp, const ALsizei SamplesToDo)
{
const ALsizei index = Comp->LookAhead;
- ALfloat *restrict sideChain = Comp->SideChain;
+ ALfloat *RESTRICT sideChain = Comp->SideChain;
SlidingHold *hold = Comp->Hold;
ALsizei i;
@@ -260,8 +273,8 @@ static void GainCompressor(Compressor *Comp, const ALsizei SamplesToDo)
const ALfloat release = Comp->Release;
const ALfloat c_est = Comp->GainEstimate;
const ALfloat a_adp = Comp->AdaptCoeff;
- const ALfloat *restrict crestFactor = Comp->CrestFactor;
- ALfloat *restrict sideChain = Comp->SideChain;
+ const ALfloat *RESTRICT crestFactor = Comp->CrestFactor;
+ ALfloat *RESTRICT sideChain = Comp->SideChain;
ALfloat postGain = Comp->PostGain;
ALfloat knee = Comp->Knee;
ALfloat t_att = attack;
@@ -353,13 +366,13 @@ static void GainCompressor(Compressor *Comp, const ALsizei SamplesToDo)
* reaching the offending impulse. This is best used when operating as a
* limiter.
*/
-static void SignalDelay(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*restrict OutBuffer)[BUFFERSIZE])
+static void SignalDelay(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE])
{
const ALsizei mask = BUFFERSIZE - 1;
const ALsizei numChans = Comp->NumChans;
const ALsizei indexIn = Comp->DelayIndex;
const ALsizei indexOut = Comp->DelayIndex - Comp->LookAhead;
- ALfloat (*restrict delay)[BUFFERSIZE] = Comp->Delay;
+ ALfloat (*RESTRICT delay)[BUFFERSIZE] = Comp->Delay;
ALsizei c, i;
ASSUME(SamplesToDo > 0);
@@ -463,14 +476,14 @@ Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate,
if(hold > 0)
{
Comp->Hold = (SlidingHold*)(Comp + 1);
- Comp->Hold->Values[0] = -INFINITY;
+ Comp->Hold->Values[0] = -HUGE_VALF;
Comp->Hold->Expiries[0] = hold;
Comp->Hold->Length = hold;
- Comp->Delay = (ALfloat(*)[])(Comp->Hold + 1);
+ Comp->Delay = (ALfloat(*)[BUFFERSIZE])(Comp->Hold + 1);
}
else
{
- Comp->Delay = (ALfloat(*)[])(Comp + 1);
+ Comp->Delay = (ALfloat(*)[BUFFERSIZE])(Comp + 1);
}
}
@@ -481,11 +494,11 @@ Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRate,
return Comp;
}
-void ApplyCompression(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*restrict OutBuffer)[BUFFERSIZE])
+void ApplyCompression(Compressor *Comp, const ALsizei SamplesToDo, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE])
{
const ALsizei numChans = Comp->NumChans;
const ALfloat preGain = Comp->PreGain;
- ALfloat *restrict sideChain;
+ ALfloat *RESTRICT sideChain;
ALsizei c, i;
ASSUME(SamplesToDo > 0);
diff --git a/Alc/mastering.h b/Alc/mastering.h
index b68b0de1..17f5e8be 100644
--- a/Alc/mastering.h
+++ b/Alc/mastering.h
@@ -42,7 +42,7 @@ struct Compressor* CompressorInit(const ALsizei NumChans, const ALuint SampleRat
const ALfloat AttackTime, const ALfloat ReleaseTime);
void ApplyCompression(struct Compressor *Comp, const ALsizei SamplesToDo,
- ALfloat (*restrict OutBuffer)[BUFFERSIZE]);
+ ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE]);
ALsizei GetCompressorLookAhead(const struct Compressor *Comp);
diff --git a/Alc/mixer/defs.h b/Alc/mixer/defs.h
index 8f6e3755..acb8a8c2 100644
--- a/Alc/mixer/defs.h
+++ b/Alc/mixer/defs.h
@@ -12,57 +12,57 @@ struct MixHrtfParams;
struct HrtfState;
/* C resamplers */
-const ALfloat *Resample_copy_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
-const ALfloat *Resample_point_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
-const ALfloat *Resample_lerp_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
-const ALfloat *Resample_cubic_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
-const ALfloat *Resample_bsinc_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
+const ALfloat *Resample_copy_C(const InterpState *state, const ALfloat *RESTRICT src, ALsizei frac, ALint increment, ALfloat *RESTRICT dst, ALsizei dstlen);
+const ALfloat *Resample_point_C(const InterpState *state, const ALfloat *RESTRICT src, ALsizei frac, ALint increment, ALfloat *RESTRICT dst, ALsizei dstlen);
+const ALfloat *Resample_lerp_C(const InterpState *state, const ALfloat *RESTRICT src, ALsizei frac, ALint increment, ALfloat *RESTRICT dst, ALsizei dstlen);
+const ALfloat *Resample_cubic_C(const InterpState *state, const ALfloat *RESTRICT src, ALsizei frac, ALint increment, ALfloat *RESTRICT dst, ALsizei dstlen);
+const ALfloat *Resample_bsinc_C(const InterpState *state, const ALfloat *RESTRICT src, ALsizei frac, ALint increment, ALfloat *RESTRICT dst, ALsizei dstlen);
/* C mixers */
-void MixHrtf_C(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixHrtf_C(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, struct MixHrtfParams *hrtfparams,
struct HrtfState *hrtfstate, ALsizei BufferSize);
-void MixHrtfBlend_C(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixHrtfBlend_C(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, const HrtfParams *oldparams,
MixHrtfParams *newparams, HrtfState *hrtfstate,
ALsizei BufferSize);
-void MixDirectHrtf_C(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixDirectHrtf_C(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
- const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2],
+ const ALfloat (*RESTRICT Coeffs)[2], ALfloat (*RESTRICT Values)[2],
ALsizei BufferSize);
-void Mix_C(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+void Mix_C(const ALfloat *data, ALsizei OutChans, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE],
ALfloat *CurrentGains, const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
ALsizei BufferSize);
void MixRow_C(ALfloat *OutBuffer, const ALfloat *Gains,
- const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
+ const ALfloat (*RESTRICT data)[BUFFERSIZE], ALsizei InChans,
ALsizei InPos, ALsizei BufferSize);
/* SSE mixers */
-void MixHrtf_SSE(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixHrtf_SSE(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, struct MixHrtfParams *hrtfparams,
struct HrtfState *hrtfstate, ALsizei BufferSize);
-void MixHrtfBlend_SSE(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixHrtfBlend_SSE(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, const HrtfParams *oldparams,
MixHrtfParams *newparams, HrtfState *hrtfstate,
ALsizei BufferSize);
-void MixDirectHrtf_SSE(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixDirectHrtf_SSE(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
- const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2],
+ const ALfloat (*RESTRICT Coeffs)[2], ALfloat (*RESTRICT Values)[2],
ALsizei BufferSize);
-void Mix_SSE(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+void Mix_SSE(const ALfloat *data, ALsizei OutChans, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE],
ALfloat *CurrentGains, const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
ALsizei BufferSize);
void MixRow_SSE(ALfloat *OutBuffer, const ALfloat *Gains,
- const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
+ const ALfloat (*RESTRICT data)[BUFFERSIZE], ALsizei InChans,
ALsizei InPos, ALsizei BufferSize);
/* SSE resamplers */
-inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *restrict frac_arr, ALsizei *restrict pos_arr, ALsizei size)
+inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *RESTRICT frac_arr, ALsizei *RESTRICT pos_arr, ALsizei size)
{
ALsizei i;
@@ -76,44 +76,44 @@ inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *restr
}
}
-const ALfloat *Resample_lerp_SSE2(const InterpState *state, const ALfloat *restrict src,
- ALsizei frac, ALint increment, ALfloat *restrict dst,
+const ALfloat *Resample_lerp_SSE2(const InterpState *state, const ALfloat *RESTRICT src,
+ ALsizei frac, ALint increment, ALfloat *RESTRICT dst,
ALsizei numsamples);
-const ALfloat *Resample_lerp_SSE41(const InterpState *state, const ALfloat *restrict src,
- ALsizei frac, ALint increment, ALfloat *restrict dst,
+const ALfloat *Resample_lerp_SSE41(const InterpState *state, const ALfloat *RESTRICT src,
+ ALsizei frac, ALint increment, ALfloat *RESTRICT dst,
ALsizei numsamples);
-const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *restrict src,
- ALsizei frac, ALint increment, ALfloat *restrict dst,
+const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *RESTRICT src,
+ ALsizei frac, ALint increment, ALfloat *RESTRICT dst,
ALsizei dstlen);
/* Neon mixers */
-void MixHrtf_Neon(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixHrtf_Neon(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, struct MixHrtfParams *hrtfparams,
struct HrtfState *hrtfstate, ALsizei BufferSize);
-void MixHrtfBlend_Neon(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixHrtfBlend_Neon(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, const HrtfParams *oldparams,
MixHrtfParams *newparams, HrtfState *hrtfstate,
ALsizei BufferSize);
-void MixDirectHrtf_Neon(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixDirectHrtf_Neon(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
- const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2],
+ const ALfloat (*RESTRICT Coeffs)[2], ALfloat (*RESTRICT Values)[2],
ALsizei BufferSize);
-void Mix_Neon(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+void Mix_Neon(const ALfloat *data, ALsizei OutChans, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE],
ALfloat *CurrentGains, const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
ALsizei BufferSize);
void MixRow_Neon(ALfloat *OutBuffer, const ALfloat *Gains,
- const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
+ const ALfloat (*RESTRICT data)[BUFFERSIZE], ALsizei InChans,
ALsizei InPos, ALsizei BufferSize);
/* Neon resamplers */
-const ALfloat *Resample_lerp_Neon(const InterpState *state, const ALfloat *restrict src,
- ALsizei frac, ALint increment, ALfloat *restrict dst,
+const ALfloat *Resample_lerp_Neon(const InterpState *state, const ALfloat *RESTRICT src,
+ ALsizei frac, ALint increment, ALfloat *RESTRICT dst,
ALsizei numsamples);
-const ALfloat *Resample_bsinc_Neon(const InterpState *state, const ALfloat *restrict src,
- ALsizei frac, ALint increment, ALfloat *restrict dst,
+const ALfloat *Resample_bsinc_Neon(const InterpState *state, const ALfloat *RESTRICT src,
+ ALsizei frac, ALint increment, ALfloat *RESTRICT dst,
ALsizei dstlen);
#endif /* MIXER_DEFS_H */
diff --git a/Alc/mixer/hrtf_inc.c b/Alc/mixer/hrtf_inc.c
index 3ef22f24..21840abd 100644
--- a/Alc/mixer/hrtf_inc.c
+++ b/Alc/mixer/hrtf_inc.c
@@ -9,13 +9,13 @@
#include "defs.h"
-static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
+static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*RESTRICT Values)[2],
const ALsizei irSize,
- const ALfloat (*restrict Coeffs)[2],
+ const ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right);
-void MixHrtf(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixHrtf(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, MixHrtfParams *hrtfparams, HrtfState *hrtfstate,
ALsizei BufferSize)
@@ -54,7 +54,7 @@ void MixHrtf(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
hrtfparams->Gain = gain + gainstep*stepcount;
}
-void MixHrtfBlend(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixHrtfBlend(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, const HrtfParams *oldparams,
MixHrtfParams *newparams, HrtfState *hrtfstate,
@@ -103,9 +103,9 @@ void MixHrtfBlend(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
newparams->Gain = newGain + newGainStep*stepcount;
}
-void MixDirectHrtf(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+void MixDirectHrtf(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
- const ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2],
+ const ALfloat (*RESTRICT Coeffs)[2], ALfloat (*RESTRICT Values)[2],
ALsizei BufferSize)
{
ALfloat insample;
diff --git a/Alc/mixer/mixer_c.c b/Alc/mixer/mixer_c.c
index 14d7c669..ea864dbc 100644
--- a/Alc/mixer/mixer_c.c
+++ b/Alc/mixer/mixer_c.c
@@ -9,13 +9,13 @@
#include "defs.h"
-static inline ALfloat do_point(const InterpState* UNUSED(state), const ALfloat *restrict vals, ALsizei UNUSED(frac))
+static inline ALfloat do_point(const InterpState* UNUSED(state), const ALfloat *RESTRICT vals, ALsizei UNUSED(frac))
{ return vals[0]; }
-static inline ALfloat do_lerp(const InterpState* UNUSED(state), const ALfloat *restrict vals, ALsizei frac)
+static inline ALfloat do_lerp(const InterpState* UNUSED(state), const ALfloat *RESTRICT vals, ALsizei frac)
{ return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); }
-static inline ALfloat do_cubic(const InterpState* UNUSED(state), const ALfloat *restrict vals, ALsizei frac)
+static inline ALfloat do_cubic(const InterpState* UNUSED(state), const ALfloat *RESTRICT vals, ALsizei frac)
{ return cubic(vals[0], vals[1], vals[2], vals[3], frac * (1.0f/FRACTIONONE)); }
-static inline ALfloat do_bsinc(const InterpState *state, const ALfloat *restrict vals, ALsizei frac)
+static inline ALfloat do_bsinc(const InterpState *state, const ALfloat *RESTRICT vals, ALsizei frac)
{
const ALfloat *fil, *scd, *phd, *spd;
ALsizei j_f, pi;
@@ -42,8 +42,8 @@ static inline ALfloat do_bsinc(const InterpState *state, const ALfloat *restrict
}
const ALfloat *Resample_copy_C(const InterpState* UNUSED(state),
- const ALfloat *restrict src, ALsizei UNUSED(frac), ALint UNUSED(increment),
- ALfloat *restrict dst, ALsizei numsamples)
+ const ALfloat *RESTRICT src, ALsizei UNUSED(frac), ALint UNUSED(increment),
+ ALfloat *RESTRICT dst, ALsizei numsamples)
{
#if defined(HAVE_SSE) || defined(HAVE_NEON)
/* Avoid copying the source data if it's aligned like the destination. */
@@ -56,8 +56,8 @@ const ALfloat *Resample_copy_C(const InterpState* UNUSED(state),
#define DECL_TEMPLATE(Tag, Sampler, O) \
const ALfloat *Resample_##Tag##_C(const InterpState *state, \
- const ALfloat *restrict src, ALsizei frac, ALint increment, \
- ALfloat *restrict dst, ALsizei numsamples) \
+ const ALfloat *RESTRICT src, ALsizei frac, ALint increment, \
+ ALfloat *RESTRICT dst, ALsizei numsamples) \
{ \
const InterpState istate = *state; \
ALsizei i; \
@@ -84,9 +84,9 @@ DECL_TEMPLATE(bsinc, do_bsinc, istate.bsinc.l)
#undef DECL_TEMPLATE
-static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
+static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*RESTRICT Values)[2],
const ALsizei IrSize,
- const ALfloat (*restrict Coeffs)[2],
+ const ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right)
{
ALsizei c;
@@ -104,7 +104,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
#include "hrtf_inc.c"
-void Mix_C(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+void Mix_C(const ALfloat *data, ALsizei OutChans, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE],
ALfloat *CurrentGains, const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
ALsizei BufferSize)
{
@@ -150,7 +150,7 @@ void Mix_C(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffer)[
* transform. And as the matrices are more or less static once set up, no
* stepping is necessary.
*/
-void MixRow_C(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans, ALsizei InPos, ALsizei BufferSize)
+void MixRow_C(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*RESTRICT data)[BUFFERSIZE], ALsizei InChans, ALsizei InPos, ALsizei BufferSize)
{
ALsizei c, i;
diff --git a/Alc/mixer/mixer_neon.c b/Alc/mixer/mixer_neon.c
index 9bf5521a..a035abc7 100644
--- a/Alc/mixer/mixer_neon.c
+++ b/Alc/mixer/mixer_neon.c
@@ -11,8 +11,8 @@
const ALfloat *Resample_lerp_Neon(const InterpState* UNUSED(state),
- const ALfloat *restrict src, ALsizei frac, ALint increment,
- ALfloat *restrict dst, ALsizei numsamples)
+ const ALfloat *RESTRICT src, ALsizei frac, ALint increment,
+ ALfloat *RESTRICT dst, ALsizei numsamples)
{
const int32x4_t increment4 = vdupq_n_s32(increment*4);
const float32x4_t fracOne4 = vdupq_n_f32(1.0f/FRACTIONONE);
@@ -67,8 +67,8 @@ const ALfloat *Resample_lerp_Neon(const InterpState* UNUSED(state),
}
const ALfloat *Resample_bsinc_Neon(const InterpState *state,
- const ALfloat *restrict src, ALsizei frac, ALint increment,
- ALfloat *restrict dst, ALsizei dstlen)
+ const ALfloat *RESTRICT src, ALsizei frac, ALint increment,
+ ALfloat *RESTRICT dst, ALsizei dstlen)
{
const ALfloat *const filter = state->bsinc.filter;
const float32x4_t sf4 = vdupq_n_f32(state->bsinc.sf);
@@ -127,9 +127,9 @@ const ALfloat *Resample_bsinc_Neon(const InterpState *state,
}
-static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
+static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*RESTRICT Values)[2],
const ALsizei IrSize,
- const ALfloat (*restrict Coeffs)[2],
+ const ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right)
{
ALsizei c;
@@ -163,7 +163,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
#include "hrtf_inc.c"
-void Mix_Neon(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+void Mix_Neon(const ALfloat *data, ALsizei OutChans, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE],
ALfloat *CurrentGains, const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
ALsizei BufferSize)
{
@@ -251,7 +251,7 @@ void Mix_Neon(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffe
}
}
-void MixRow_Neon(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans, ALsizei InPos, ALsizei BufferSize)
+void MixRow_Neon(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*RESTRICT data)[BUFFERSIZE], ALsizei InChans, ALsizei InPos, ALsizei BufferSize)
{
ALsizei c;
diff --git a/Alc/mixer/mixer_sse.c b/Alc/mixer/mixer_sse.c
index 725a5ebc..34055001 100644
--- a/Alc/mixer/mixer_sse.c
+++ b/Alc/mixer/mixer_sse.c
@@ -12,8 +12,8 @@
#include "defs.h"
-const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *restrict src,
- ALsizei frac, ALint increment, ALfloat *restrict dst,
+const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *RESTRICT src,
+ ALsizei frac, ALint increment, ALfloat *RESTRICT dst,
ALsizei dstlen)
{
const ALfloat *const filter = state->bsinc.filter;
@@ -75,9 +75,9 @@ const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *restr
}
-static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
+static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*RESTRICT Values)[2],
const ALsizei IrSize,
- const ALfloat (*restrict Coeffs)[2],
+ const ALfloat (*RESTRICT Coeffs)[2],
ALfloat left, ALfloat right)
{
const __m128 lrlr = _mm_setr_ps(left, right, left, right);
@@ -135,7 +135,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
#include "hrtf_inc.c"
-void Mix_SSE(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+void Mix_SSE(const ALfloat *data, ALsizei OutChans, ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE],
ALfloat *CurrentGains, const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
ALsizei BufferSize)
{
@@ -218,7 +218,7 @@ void Mix_SSE(const ALfloat *data, ALsizei OutChans, ALfloat (*restrict OutBuffer
}
}
-void MixRow_SSE(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans, ALsizei InPos, ALsizei BufferSize)
+void MixRow_SSE(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*RESTRICT data)[BUFFERSIZE], ALsizei InChans, ALsizei InPos, ALsizei BufferSize)
{
ALsizei c;
diff --git a/Alc/mixer/mixer_sse2.c b/Alc/mixer/mixer_sse2.c
index 9cbaeb0a..2432342f 100644
--- a/Alc/mixer/mixer_sse2.c
+++ b/Alc/mixer/mixer_sse2.c
@@ -28,8 +28,8 @@
const ALfloat *Resample_lerp_SSE2(const InterpState* UNUSED(state),
- const ALfloat *restrict src, ALsizei frac, ALint increment,
- ALfloat *restrict dst, ALsizei numsamples)
+ const ALfloat *RESTRICT src, ALsizei frac, ALint increment,
+ ALfloat *RESTRICT dst, ALsizei numsamples)
{
const __m128i increment4 = _mm_set1_epi32(increment*4);
const __m128 fracOne4 = _mm_set1_ps(1.0f/FRACTIONONE);
diff --git a/Alc/mixer/mixer_sse41.c b/Alc/mixer/mixer_sse41.c
index e92a3dd0..34b405f8 100644
--- a/Alc/mixer/mixer_sse41.c
+++ b/Alc/mixer/mixer_sse41.c
@@ -29,8 +29,8 @@
const ALfloat *Resample_lerp_SSE41(const InterpState* UNUSED(state),
- const ALfloat *restrict src, ALsizei frac, ALint increment,
- ALfloat *restrict dst, ALsizei numsamples)
+ const ALfloat *RESTRICT src, ALsizei frac, ALint increment,
+ ALfloat *RESTRICT dst, ALsizei numsamples)
{
const __m128i increment4 = _mm_set1_epi32(increment*4);
const __m128 fracOne4 = _mm_set1_ps(1.0f/FRACTIONONE);
diff --git a/Alc/mixvoice.c b/Alc/mixvoice.c
index d019b898..587f4a6b 100644
--- a/Alc/mixvoice.c
+++ b/Alc/mixvoice.c
@@ -45,7 +45,7 @@
static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
"MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
-extern inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *restrict frac_arr, ALsizei *restrict pos_arr, ALsizei size);
+extern inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *RESTRICT frac_arr, ALsizei *RESTRICT pos_arr, ALsizei size);
/* BSinc24 requires up to 23 extra samples before the current position, and 24 after. */
@@ -228,7 +228,7 @@ static inline ALfloat Sample_ALalaw(ALalaw val)
{ return aLawDecompressionTable[val] * (1.0f/32768.0f); }
#define DECL_TEMPLATE(T) \
-static inline void Load_##T(ALfloat *restrict dst, const T *restrict src, \
+static inline void Load_##T(ALfloat *RESTRICT dst, const T *RESTRICT src, \
ALint srcstep, ALsizei samples) \
{ \
ALsizei i; \
@@ -245,7 +245,7 @@ DECL_TEMPLATE(ALalaw)
#undef DECL_TEMPLATE
-static void LoadSamples(ALfloat *restrict dst, const ALvoid *restrict src, ALint srcstep,
+static void LoadSamples(ALfloat *RESTRICT dst, const ALvoid *RESTRICT src, ALint srcstep,
enum FmtType srctype, ALsizei samples)
{
#define HANDLE_FMT(ET, ST) case ET: Load_##ST(dst, src, srcstep, samples); break
@@ -263,7 +263,7 @@ static void LoadSamples(ALfloat *restrict dst, const ALvoid *restrict src, ALint
static const ALfloat *DoFilters(BiquadFilter *lpfilter, BiquadFilter *hpfilter,
- ALfloat *restrict dst, const ALfloat *restrict src,
+ ALfloat *RESTRICT dst, const ALfloat *RESTRICT src,
ALsizei numsamples, enum ActiveFilters type)
{
ALsizei i;
diff --git a/Alc/panning.c b/Alc/panning.cpp
index 2c0f3bf2..db476884 100644
--- a/Alc/panning.c
+++ b/Alc/panning.cpp
@@ -38,12 +38,6 @@
#include "bs2b.h"
-extern inline void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
-extern inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
-extern inline float ScaleAzimuthFront(float azimuth, float scale);
-extern inline void ComputePanGains(const MixParams *dry, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
-
-
static const ALsizei FuMa2ACN[MAX_AMBI_COEFFS] = {
0, /* W */
3, /* X */
@@ -151,7 +145,7 @@ void CalcAmbiCoeffs(const ALfloat y, const ALfloat z, const ALfloat x, const ALf
}
-void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat*RESTRICT coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
{
ALsizei i, j;
@@ -166,7 +160,7 @@ void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, AL
gains[i] = 0.0f;
}
-void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat*RESTRICT coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
{
ALsizei i;
@@ -281,50 +275,50 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei sp
* use the side channels when the device is configured for back,
* and vice-versa.
*/
- if(alstr_cmp_cstr(conf->Speakers[i].Name, "LF") == 0)
+ if(conf->Speakers[i].Name == "LF")
ch = FrontLeft;
- else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RF") == 0)
+ else if(conf->Speakers[i].Name == "RF")
ch = FrontRight;
- else if(alstr_cmp_cstr(conf->Speakers[i].Name, "CE") == 0)
+ else if(conf->Speakers[i].Name == "CE")
ch = FrontCenter;
- else if(alstr_cmp_cstr(conf->Speakers[i].Name, "LS") == 0)
+ else if(conf->Speakers[i].Name == "LS")
{
if(device->FmtChans == DevFmtX51Rear)
ch = BackLeft;
else
ch = SideLeft;
}
- else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RS") == 0)
+ else if(conf->Speakers[i].Name == "RS")
{
if(device->FmtChans == DevFmtX51Rear)
ch = BackRight;
else
ch = SideRight;
}
- else if(alstr_cmp_cstr(conf->Speakers[i].Name, "LB") == 0)
+ else if(conf->Speakers[i].Name == "LB")
{
if(device->FmtChans == DevFmtX51)
ch = SideLeft;
else
ch = BackLeft;
}
- else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RB") == 0)
+ else if(conf->Speakers[i].Name == "RB")
{
if(device->FmtChans == DevFmtX51)
ch = SideRight;
else
ch = BackRight;
}
- else if(alstr_cmp_cstr(conf->Speakers[i].Name, "CB") == 0)
+ else if(conf->Speakers[i].Name == "CB")
ch = BackCenter;
else
{
- const char *name = alstr_get_cstr(conf->Speakers[i].Name);
+ const char *name = conf->Speakers[i].Name.c_str();
unsigned int n;
char c;
if(sscanf(name, "AUX%u%c", &n, &c) == 1 && n < 16)
- ch = Aux0+n;
+ ch = static_cast<enum Channel>(Aux0+n);
else
{
ERR("AmbDec speaker label \"%s\" not recognized\n", name);
@@ -335,7 +329,7 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei sp
if(chidx == -1)
{
ERR("Failed to lookup AmbDec speaker label %s\n",
- alstr_get_cstr(conf->Speakers[i].Name));
+ conf->Speakers[i].Name.c_str());
return false;
}
speakermap[i] = chidx;
@@ -381,7 +375,7 @@ static const ChannelMap MonoCfg[1] = {
};
static void InitNearFieldCtrl(ALCdevice *device, ALfloat ctrl_dist, ALsizei order,
- const ALsizei *restrict chans_per_order)
+ const ALsizei *RESTRICT chans_per_order)
{
const char *devname = alstr_get_cstr(device->DeviceName);
ALsizei i;
@@ -429,14 +423,14 @@ static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const AL
srate + 0.5f);
if(delay >= (ALfloat)MAX_DELAY_LENGTH)
ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
- alstr_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH);
+ conf->Speakers[i].Name.c_str(), delay, MAX_DELAY_LENGTH);
device->ChannelDelay[chan].Length = (ALsizei)clampf(
delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1)
);
device->ChannelDelay[chan].Gain = conf->Speakers[i].Distance / maxdist;
TRACE("Channel %u \"%s\" distance compensation: %d samples, %f gain\n", chan,
- alstr_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length,
+ conf->Speakers[i].Name.c_str(), device->ChannelDelay[chan].Length,
device->ChannelDelay[chan].Gain
);
@@ -449,7 +443,8 @@ static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const AL
if(total > 0)
{
- device->ChannelDelay[0].Buffer = al_calloc(16, total * sizeof(ALfloat));
+ device->ChannelDelay[0].Buffer = reinterpret_cast<float*>(
+ al_calloc(16, total * sizeof(ALfloat)));
for(i = 1;i < MAX_OUTPUT_CHANNELS;i++)
{
size_t len = RoundUp(device->ChannelDelay[i-1].Length, 4);
@@ -644,9 +639,9 @@ static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const A
}
}
- if(conf->CoeffScale == ADS_SN3D)
+ if(conf->CoeffScale == AmbDecScale::SN3D)
coeff_scale = SN3D2N3DScale;
- else if(conf->CoeffScale == ADS_FuMa)
+ else if(conf->CoeffScale == AmbDecScale::FuMa)
coeff_scale = FuMa2N3DScale;
for(i = 0;i < conf->NumSpeakers;i++)
@@ -730,7 +725,7 @@ static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsiz
);
bformatdec_reset(device->AmbiDecoder, conf, count, device->Frequency, speakermap);
- if(!(conf->ChanMask > 0xf))
+ if(conf->ChanMask <= 0xf)
{
device->FOAOut.Ambi = device->Dry.Ambi;
device->FOAOut.CoeffCount = device->Dry.CoeffCount;
@@ -845,8 +840,8 @@ static void InitHrtfPanning(ALCdevice *device)
};
static const ALsizei IndexMap[6] = { 0, 1, 2, 3, 4, 8 };
static const ALsizei ChansPerOrder[MAX_AMBI_ORDER+1] = { 1, 3, 2, 0 };
- const ALfloat (*restrict AmbiMatrix)[MAX_AMBI_COEFFS] = AmbiMatrixFOA;
- const ALfloat *restrict AmbiOrderHFGain = AmbiOrderHFGainFOA;
+ const ALfloat (*RESTRICT AmbiMatrix)[MAX_AMBI_COEFFS] = AmbiMatrixFOA;
+ const ALfloat *RESTRICT AmbiOrderHFGain = AmbiOrderHFGainFOA;
ALsizei count = 4;
ALsizei i;
@@ -860,7 +855,8 @@ static void InitHrtfPanning(ALCdevice *device)
count = COUNTOF(IndexMap);
}
- device->Hrtf = al_calloc(16, FAM_SIZE(DirectHrtfState, Chan, count));
+ device->Hrtf = reinterpret_cast<DirectHrtfState*>(
+ al_calloc(16, FAM_SIZE(DirectHrtfState, Chan, count)));
for(i = 0;i < count;i++)
{
@@ -967,8 +963,6 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
if(hrtf_appreq == Hrtf_Enable)
device->HrtfStatus = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT;
- ambdec_init(&conf);
-
devname = alstr_get_cstr(device->DeviceName);
switch(device->FmtChans)
{
@@ -988,7 +982,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
const char *fname;
if(ConfigValueStr(devname, "decoder", layout, &fname))
{
- if(!ambdec_load(&conf, fname))
+ if(!conf.load(fname))
ERR("Failed to load layout file %s\n", fname);
else
{
@@ -1044,7 +1038,8 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
* higher).
*/
ALfloat scale = (ALfloat)(5000.0 / device->Frequency);
- FrontStablizer *stablizer = al_calloc(16, sizeof(*stablizer));
+ FrontStablizer *stablizer = reinterpret_cast<FrontStablizer*>(
+ al_calloc(16, sizeof(*stablizer)));
bandsplit_init(&stablizer->LFilter, scale);
stablizer->RFilter = stablizer->LFilter;
@@ -1065,7 +1060,6 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
}
TRACE("Front stablizer %s\n", device->Stablizer ? "enabled" : "disabled");
- ambdec_deinit(&conf);
return;
}
@@ -1194,7 +1188,7 @@ no_hrtf:
ConfigValueInt(alstr_get_cstr(device->DeviceName), NULL, "cf_level", &bs2blevel);
if(bs2blevel > 0 && bs2blevel <= 6)
{
- device->Bs2b = al_calloc(16, sizeof(*device->Bs2b));
+ device->Bs2b = reinterpret_cast<struct bs2b*>(al_calloc(16, sizeof(*device->Bs2b)));
bs2b_set_params(device->Bs2b, bs2blevel, device->Frequency);
TRACE("BS2B enabled\n");
InitPanning(device);
@@ -1212,7 +1206,7 @@ no_hrtf:
}
if(device->Render_Mode == NormalRender)
{
- device->Uhj_Encoder = al_calloc(16, sizeof(Uhj2Encoder));
+ device->Uhj_Encoder = reinterpret_cast<Uhj2Encoder*>(al_calloc(16, sizeof(Uhj2Encoder)));
TRACE("UHJ enabled\n");
InitUhjPanning(device);
return;
diff --git a/Alc/polymorphism.h b/Alc/polymorphism.h
index fa31fad2..83d5585f 100644
--- a/Alc/polymorphism.h
+++ b/Alc/polymorphism.h
@@ -2,9 +2,15 @@
#define POLYMORPHISM_H
/* Macros to declare inheriting types, and to (down-)cast and up-cast. */
+#ifdef __cplusplus
+#define STATIC_CAST(to, obj) static_cast<to*>(obj)
+#define STATIC_UPCAST(to, from, obj) static_cast<to*>(obj)
+#else
+
#define DERIVE_FROM_TYPE(t) t t##_parent
#define STATIC_CAST(to, obj) (&(obj)->to##_parent)
-#ifdef __GNUC__
+
+#if defined(__GNUC__)
#define STATIC_UPCAST(to, from, obj) __extension__({ \
static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))), \
"Invalid upcast object from type"); \
@@ -13,6 +19,7 @@
#else
#define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent)))
#endif
+#endif /* __cplusplus */
/* Defines method forwards, which call the given parent's (T2's) implementation. */
#define DECLARE_FORWARD(T1, T2, rettype, func) \
@@ -54,7 +61,7 @@ static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c, a
/* Defines the default functions used to (de)allocate a polymorphic object. */
#define DECLARE_DEFAULT_ALLOCATORS(T) \
-static void* T##_New(size_t size) { return al_malloc(16, size); } \
+static void* T##_New(size_t size) { return al_calloc(16, size); } \
static void T##_Delete(void *ptr) { al_free(ptr); }
@@ -74,17 +81,15 @@ static void T##_Delete(void *ptr) { al_free(ptr); }
/* Allocate and construct an object, with arguments. */
#define NEW_OBJ(_res, T) do { \
- _res = T##_New(sizeof(T)); \
+ _res = (T*)T##_New(sizeof(T)); \
if(_res) \
{ \
- memset(_res, 0, sizeof(T)); \
T##_Construct(_res, EXTRACT_NEW_ARGS
/* Allocate and construct an object, with no arguments. */
#define NEW_OBJ0(_res, T) do { \
- _res = T##_New(sizeof(T)); \
+ _res = (T*)T##_New(sizeof(T)); \
if(_res) \
{ \
- memset(_res, 0, sizeof(T)); \
T##_Construct(_res EXTRACT_NEW_ARGS
/* Destructs and deallocate an object. */
diff --git a/Alc/uhjfilter.c b/Alc/uhjfilter.cpp
index 42b0bc40..4fae721f 100644
--- a/Alc/uhjfilter.c
+++ b/Alc/uhjfilter.cpp
@@ -4,19 +4,21 @@
#include "alu.h"
#include "uhjfilter.h"
+namespace {
+
/* This is the maximum number of samples processed for each inner loop
* iteration. */
#define MAX_UPDATE_SAMPLES 128
-static const ALfloat Filter1CoeffSqr[4] = {
+constexpr ALfloat Filter1CoeffSqr[4] = {
0.479400865589f, 0.876218493539f, 0.976597589508f, 0.997499255936f
};
-static const ALfloat Filter2CoeffSqr[4] = {
+constexpr ALfloat Filter2CoeffSqr[4] = {
0.161758498368f, 0.733028932341f, 0.945349700329f, 0.990599156685f
};
-static void allpass_process(AllPassState *state, ALfloat *restrict dst, const ALfloat *restrict src, const ALfloat aa, ALsizei todo)
+void allpass_process(AllPassState *state, ALfloat *RESTRICT dst, const ALfloat *RESTRICT src, const ALfloat aa, ALsizei todo)
{
ALfloat z1 = state->z[0];
ALfloat z2 = state->z[1];
@@ -34,6 +36,8 @@ static void allpass_process(AllPassState *state, ALfloat *restrict dst, const AL
state->z[1] = z2;
}
+} // namespace
+
/* NOTE: There seems to be a bit of an inconsistency in how this encoding is
* supposed to work. Some references, such as
@@ -55,7 +59,7 @@ static void allpass_process(AllPassState *state, ALfloat *restrict dst, const AL
* know which is the intended result.
*/
-void EncodeUhj2(Uhj2Encoder *enc, ALfloat *restrict LeftOut, ALfloat *restrict RightOut, ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
+void EncodeUhj2(Uhj2Encoder *enc, ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, ALfloat (*RESTRICT InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
{
ALfloat D[MAX_UPDATE_SAMPLES], S[MAX_UPDATE_SAMPLES];
ALfloat temp[2][MAX_UPDATE_SAMPLES];
diff --git a/Alc/uhjfilter.h b/Alc/uhjfilter.h
index e773e0a7..211425ed 100644
--- a/Alc/uhjfilter.h
+++ b/Alc/uhjfilter.h
@@ -5,6 +5,10 @@
#include "alMain.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct AllPassState {
ALfloat z[2];
} AllPassState;
@@ -44,6 +48,10 @@ typedef struct Uhj2Encoder {
/* Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input
* signal. The input must use FuMa channel ordering and scaling.
*/
-void EncodeUhj2(Uhj2Encoder *enc, ALfloat *restrict LeftOut, ALfloat *restrict RightOut, ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
+void EncodeUhj2(Uhj2Encoder *enc, ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut, ALfloat (*RESTRICT InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
#endif /* UHJFILTER_H */
diff --git a/Alc/vector.h b/Alc/vector.h
index ed9acfb0..a7be99d0 100644
--- a/Alc/vector.h
+++ b/Alc/vector.h
@@ -26,6 +26,7 @@ typedef const _##N* const_##N;
#define VECTOR_INIT_STATIC() NULL
#define VECTOR_DEINIT(_x) do { al_free((_x)); (_x) = NULL; } while(0)
+#ifndef __cplusplus
#define VECTOR_RESIZE(_x, _s, _c) do { \
size_t _size = (_s); \
size_t _cap = (_c); \
@@ -55,6 +56,37 @@ typedef const _##N* const_##N;
(_x)->Size = _size; \
} while(0) \
+#else
+
+template<typename T>
+inline void do_vector_resize(T *&vec, size_t size, size_t cap)
+{
+ if(size > cap)
+ cap = size;
+
+ if(!vec && cap == 0)
+ return;
+
+ if((vec ? vec->Capacity : 0) < cap)
+ {
+ ptrdiff_t data_offset = vec ? (char*)(vec->Data) - (char*)(vec) : sizeof(*vec);
+ size_t old_size = (vec ? vec->Size : 0);
+ T *temp;
+
+ temp = reinterpret_cast<T*>(al_calloc(16, data_offset + sizeof(vec->Data[0])*cap));
+ assert(temp != nullptr);
+ if(vec)
+ memcpy(temp->Data, vec->Data, sizeof(vec->Data[0])*old_size);
+
+ al_free(vec);
+ vec = temp;
+ vec->Capacity = cap;
+ }
+ vec->Size = size;
+}
+#define VECTOR_RESIZE(_x, _s, _c) do_vector_resize(_x, _s, _c)
+#endif // __cplusplus
+
#define VECTOR_CAPACITY(_x) ((_x) ? (_x)->Capacity : 0)
#define VECTOR_SIZE(_x) ((_x) ? (_x)->Size : 0)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6fea142a..ba1db905 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,6 +16,9 @@ IF(COMMAND CMAKE_POLICY)
IF(POLICY CMP0054)
CMAKE_POLICY(SET CMP0054 NEW)
ENDIF(POLICY CMP0054)
+ IF(POLICY CMP0075)
+ CMAKE_POLICY(SET CMP0075 NEW)
+ ENDIF(POLICY CMP0075)
ENDIF(COMMAND CMAKE_POLICY)
SET(CMAKE_MODULE_PATH "${OpenAL_SOURCE_DIR}/cmake")
@@ -29,6 +32,7 @@ INCLUDE(CheckSymbolExists)
INCLUDE(CheckCCompilerFlag)
INCLUDE(CheckCXXCompilerFlag)
INCLUDE(CheckCSourceCompiles)
+INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckTypeSize)
include(CheckStructHasMember)
include(CheckFileOffsetBits)
@@ -145,26 +149,29 @@ if(NOT WIN32)
UNSET(OLD_REQUIRED_FLAGS)
ENDIF()
-# Set defines for large file support
-CHECK_FILE_OFFSET_BITS()
-IF(_FILE_OFFSET_BITS)
- SET(CPP_DEFS ${CPP_DEFS} "_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}")
- SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}")
+# Set defines for large file support. Don't set this for Android targets. See:
+# https://android-developers.googleblog.com/2017/09/introducing-android-native-development.html
+IF(NOT ANDROID)
+ CHECK_FILE_OFFSET_BITS()
+ IF(_FILE_OFFSET_BITS)
+ SET(CPP_DEFS ${CPP_DEFS} "_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}")
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}")
+ ENDIF()
+ SET(CPP_DEFS ${CPP_DEFS} _LARGEFILE_SOURCE _LARGE_FILES)
+ SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_LARGEFILE_SOURCE -D_LARGE_FILES")
ENDIF()
-SET(CPP_DEFS ${CPP_DEFS} _LARGEFILE_SOURCE _LARGE_FILES)
-SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_LARGEFILE_SOURCE -D_LARGE_FILES")
-# MSVC may need workarounds for C99 restrict and inline
-IF(MSVC)
- # TODO: Once we truly require C99, these restrict and inline checks should go
- # away.
- CHECK_C_SOURCE_COMPILES("int *restrict foo;
- int main() {return 0;}" HAVE_RESTRICT)
- IF(NOT HAVE_RESTRICT)
- SET(CPP_DEFS ${CPP_DEFS} "restrict=")
- SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Drestrict=")
- ENDIF()
+# C99 has restrict, but C++ does not, so we can only utilize __restrict.
+SET(RESTRICT_DECL )
+CHECK_C_SOURCE_COMPILES("int *__restrict foo;
+ int main() {return 0;}" HAVE___RESTRICT)
+IF(HAVE___RESTRICT)
+ SET(RESTRICT_DECL "__restrict")
+ENDIF()
+# MSVC may need workarounds for C99 inline
+IF(MSVC)
+ # TODO: Once we truly require C99, this inline check should go away.
CHECK_C_SOURCE_COMPILES("inline void foo(void) { }
int main() {return 0;}" HAVE_INLINE)
IF(NOT HAVE_INLINE)
@@ -283,7 +290,7 @@ ENDIF()
IF(MSVC)
SET(CPP_DEFS ${CPP_DEFS} _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE)
- SET(C_FLAGS ${C_FLAGS} /wd4098)
+ SET(C_FLAGS ${C_FLAGS} /wd4098 /wd4200)
IF(NOT DXSDK_DIR)
STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}")
@@ -343,11 +350,57 @@ int main()
}"
HAVE_STATIC_LIBGCC_SWITCH
)
- if(HAVE_STATIC_LIBGCC_SWITCH)
- SET(LINKER_FLAGS ${LINKER_FLAGS} -static-libgcc)
+ set(CMAKE_REQUIRED_LIBRARIES ${OLD_REQUIRED_LIBRARIES})
+ unset(OLD_REQUIRED_LIBRARIES)
+
+ if(NOT HAVE_STATIC_LIBGCC_SWITCH)
+ message(FATAL_ERROR "Cannot static link libgcc")
endif()
+ set(LINKER_FLAGS ${LINKER_FLAGS} -static-libgcc)
+ endif()
+
+ option(ALSOFT_STATIC_STDCXX "Static link libstdc++" OFF)
+ if(ALSOFT_STATIC_STDCXX)
+ set(OLD_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} "-Wl,--push-state,-Bstatic,-lstdc++,--pop-state")
+ check_cxx_source_compiles(
+"#include <cstdlib>
+int main()
+{
+ return 0;
+}"
+ HAVE_STATIC_LIBSTDCXX_SWITCH
+ )
set(CMAKE_REQUIRED_LIBRARIES ${OLD_REQUIRED_LIBRARIES})
unset(OLD_REQUIRED_LIBRARIES)
+
+ if(NOT HAVE_STATIC_LIBSTDCXX_SWITCH)
+ message(FATAL_ERROR "Cannot static link libstdc++")
+ endif()
+ set(LINKER_FLAGS ${LINKER_FLAGS} "-Wl,--push-state,-Bstatic,-lstdc++,--pop-state")
+ endif()
+
+ if(WIN32)
+ option(ALSOFT_STATIC_WINPTHREAD "Static link libwinpthread" OFF)
+ if(ALSOFT_STATIC_WINPTHREAD)
+ set(OLD_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} "-Wl,--push-state,-Bstatic,-lwinpthread,--pop-state")
+ check_cxx_source_compiles(
+"#include <cstdlib>
+int main()
+{
+ return 0;
+}"
+ HAVE_STATIC_LIBWINPTHREAD_SWITCH
+ )
+ set(CMAKE_REQUIRED_LIBRARIES ${OLD_REQUIRED_LIBRARIES})
+ unset(OLD_REQUIRED_LIBRARIES)
+
+ if(NOT HAVE_STATIC_LIBWINPTHREAD_SWITCH)
+ message(FATAL_ERROR "Cannot static link libwinpthread")
+ endif()
+ set(LINKER_FLAGS ${LINKER_FLAGS} "-Wl,--push-state,-Bstatic,-lwinpthread,--pop-state")
+ endif()
endif()
ENDIF()
@@ -768,7 +821,7 @@ SET(OPENAL_OBJS
OpenAL32/Include/alAuxEffectSlot.h
OpenAL32/alAuxEffectSlot.c
OpenAL32/Include/alBuffer.h
- OpenAL32/alBuffer.c
+ OpenAL32/alBuffer.cpp
OpenAL32/Include/alEffect.h
OpenAL32/alEffect.c
OpenAL32/Include/alError.h
@@ -814,7 +867,7 @@ SET(ALC_OBJS
Alc/filters/filter.c
Alc/filters/nfc.c
Alc/filters/nfc.h
- Alc/filters/splitter.c
+ Alc/filters/splitter.cpp
Alc/filters/splitter.h
Alc/helpers.c
Alc/alstring.h
@@ -825,13 +878,13 @@ SET(ALC_OBJS
Alc/vector.h
Alc/hrtf.c
Alc/hrtf.h
- Alc/uhjfilter.c
+ Alc/uhjfilter.cpp
Alc/uhjfilter.h
- Alc/ambdec.c
+ Alc/ambdec.cpp
Alc/ambdec.h
- Alc/bformatdec.c
+ Alc/bformatdec.cpp
Alc/bformatdec.h
- Alc/panning.c
+ Alc/panning.cpp
Alc/polymorphism.h
Alc/mixvoice.c
Alc/mixer/defs.h
@@ -1098,7 +1151,7 @@ IF(HAVE_WINDOWS_H)
IF(ALSOFT_BACKEND_DSOUND)
SET(HAVE_DSOUND 1)
SET(BACKENDS "${BACKENDS} DirectSound${IS_LINKED},")
- SET(ALC_OBJS ${ALC_OBJS} Alc/backends/dsound.c)
+ SET(ALC_OBJS ${ALC_OBJS} Alc/backends/dsound.cpp)
ADD_BACKEND_LIBS(${DSOUND_LIBRARIES})
SET(INC_PATHS ${INC_PATHS} ${DSOUND_INCLUDE_DIRS})
ENDIF()
@@ -1111,7 +1164,7 @@ IF(HAVE_WINDOWS_H)
IF(ALSOFT_BACKEND_WASAPI)
SET(HAVE_WASAPI 1)
SET(BACKENDS "${BACKENDS} WASAPI,")
- SET(ALC_OBJS ${ALC_OBJS} Alc/backends/wasapi.c)
+ SET(ALC_OBJS ${ALC_OBJS} Alc/backends/wasapi.cpp)
ENDIF()
ENDIF()
@@ -1153,7 +1206,7 @@ IF(PULSEAUDIO_FOUND)
IF(ALSOFT_BACKEND_PULSEAUDIO)
SET(HAVE_PULSEAUDIO 1)
SET(BACKENDS "${BACKENDS} PulseAudio${IS_LINKED},")
- SET(ALC_OBJS ${ALC_OBJS} Alc/backends/pulseaudio.c)
+ SET(ALC_OBJS ${ALC_OBJS} Alc/backends/pulseaudio.cpp)
ADD_BACKEND_LIBS(${PULSEAUDIO_LIBRARIES})
SET(INC_PATHS ${INC_PATHS} ${PULSEAUDIO_INCLUDE_DIRS})
ENDIF()
@@ -1412,11 +1465,11 @@ ELSE()
ENDIF()
IF(WIN32 AND ALSOFT_BUILD_ROUTER)
- ADD_LIBRARY(OpenAL SHARED router/router.c router/router.h router/alc.c router/al.c)
+ ADD_LIBRARY(OpenAL SHARED router/router.cpp router/router.h router/alc.cpp router/al.cpp)
TARGET_COMPILE_DEFINITIONS(OpenAL
PRIVATE AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES ${CPP_DEFS})
TARGET_COMPILE_OPTIONS(OpenAL PRIVATE ${C_FLAGS})
- TARGET_LINK_LIBRARIES(OpenAL PRIVATE ${LINKER_FLAGS} ${COMMON_LIB})
+ TARGET_LINK_LIBRARIES(OpenAL PRIVATE ${COMMON_LIB} ${LINKER_FLAGS})
SET_TARGET_PROPERTIES(OpenAL PROPERTIES PREFIX "")
SET_TARGET_PROPERTIES(OpenAL PROPERTIES OUTPUT_NAME ${LIBNAME})
IF(TARGET build_version)
@@ -1443,7 +1496,7 @@ TARGET_INCLUDE_DIRECTORIES(${IMPL_TARGET}
PRIVATE "${OpenAL_SOURCE_DIR}/OpenAL32/Include" "${OpenAL_SOURCE_DIR}/Alc" ${INC_PATHS})
TARGET_COMPILE_OPTIONS(${IMPL_TARGET} PRIVATE ${C_FLAGS})
TARGET_LINK_LIBRARIES(${IMPL_TARGET}
- PRIVATE ${LINKER_FLAGS} ${COMMON_LIB} ${EXTRA_LIBS} ${MATH_LIB})
+ PRIVATE ${COMMON_LIB} ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB})
IF(TARGET build_version)
ADD_DEPENDENCIES(${IMPL_TARGET} build_version)
ENDIF()
diff --git a/OpenAL32/Include/alAuxEffectSlot.h b/OpenAL32/Include/alAuxEffectSlot.h
index 03ee97d6..97a3906d 100644
--- a/OpenAL32/Include/alAuxEffectSlot.h
+++ b/OpenAL32/Include/alAuxEffectSlot.h
@@ -30,7 +30,7 @@ struct ALeffectStateVtable {
ALboolean (*const deviceUpdate)(ALeffectState *state, ALCdevice *device);
void (*const update)(ALeffectState *state, const ALCcontext *context, const struct ALeffectslot *slot, const union ALeffectProps *props);
- void (*const process)(ALeffectState *state, ALsizei samplesToDo, const ALfloat (*restrict samplesIn)[BUFFERSIZE], ALfloat (*restrict samplesOut)[BUFFERSIZE], ALsizei numChannels);
+ void (*const process)(ALeffectState *state, ALsizei samplesToDo, const ALfloat (*RESTRICT samplesIn)[BUFFERSIZE], ALfloat (*RESTRICT samplesOut)[BUFFERSIZE], ALsizei numChannels);
void (*const Delete)(void *ptr);
};
@@ -44,7 +44,7 @@ typedef ALfloat ALfloatBUFFERSIZE[BUFFERSIZE];
DECLARE_THUNK(T, ALeffectState, void, Destruct) \
DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*) \
DECLARE_THUNK3(T, ALeffectState, void, update, const ALCcontext*, const ALeffectslot*, const ALeffectProps*) \
-DECLARE_THUNK4(T, ALeffectState, void, process, ALsizei, const ALfloatBUFFERSIZE*restrict, ALfloatBUFFERSIZE*restrict, ALsizei) \
+DECLARE_THUNK4(T, ALeffectState, void, process, ALsizei, const ALfloatBUFFERSIZE*RESTRICT, ALfloatBUFFERSIZE*RESTRICT, ALsizei) \
static void T##_ALeffectState_Delete(void *ptr) \
{ return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); } \
\
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 0fd77491..b3380ae2 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -914,7 +914,41 @@ int EventThread(void *arg);
vector_al_string SearchDataFiles(const char *match, const char *subdir);
#ifdef __cplusplus
-}
+} // extern "C"
+
+/* Simple RAII context reference. Takes the reference of the provided
+ * ALCcontext, and decrements it when leaving scope. Movable (transfer
+ * reference) but not copyable (no new references).
+ */
+class ContextRef {
+ ALCcontext *mCtx{nullptr};
+
+ void release() noexcept
+ {
+ if(mCtx)
+ ALCcontext_DecRef(mCtx);
+ mCtx = nullptr;
+ }
+
+public:
+ ContextRef() noexcept = default;
+ explicit ContextRef(ALCcontext *ctx) noexcept : mCtx(ctx) { }
+ ~ContextRef() { release(); }
+
+ ContextRef& operator=(const ContextRef&) = delete;
+ ContextRef& operator=(ContextRef&& rhs) noexcept
+ {
+ release();
+ mCtx = rhs.mCtx;
+ rhs.mCtx = nullptr;
+ return *this;
+ }
+
+ operator bool() const noexcept { return static_cast<bool>(mCtx); }
+
+ ALCcontext* operator->() noexcept { return mCtx; }
+ ALCcontext* get() noexcept { return mCtx; }
+};
#endif
#endif
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index c572fd71..03c388b4 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -87,8 +87,8 @@ typedef union InterpState {
} InterpState;
typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
- const ALfloat *restrict src, ALsizei frac, ALint increment,
- ALfloat *restrict dst, ALsizei dstlen
+ const ALfloat *RESTRICT src, ALsizei frac, ALint increment,
+ ALfloat *RESTRICT dst, ALsizei dstlen
);
void BsincPrepare(const ALuint increment, BsincState *state, const struct BSincTable *table);
@@ -306,25 +306,25 @@ void DeinitVoice(ALvoice *voice);
typedef void (*MixerFunc)(const ALfloat *data, ALsizei OutChans,
- ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
+ ALfloat (*RESTRICT OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains,
const ALfloat *TargetGains, ALsizei Counter, ALsizei OutPos,
ALsizei BufferSize);
typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains,
- const ALfloat (*restrict data)[BUFFERSIZE], ALsizei InChans,
+ const ALfloat (*RESTRICT data)[BUFFERSIZE], ALsizei InChans,
ALsizei InPos, ALsizei BufferSize);
-typedef void (*HrtfMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+typedef void (*HrtfMixerFunc)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, MixHrtfParams *hrtfparams,
HrtfState *hrtfstate, ALsizei BufferSize);
-typedef void (*HrtfMixerBlendFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+typedef void (*HrtfMixerBlendFunc)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, ALsizei OutPos,
const ALsizei IrSize, const HrtfParams *oldparams,
MixHrtfParams *newparams, HrtfState *hrtfstate,
ALsizei BufferSize);
-typedef void (*HrtfDirectMixerFunc)(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
+typedef void (*HrtfDirectMixerFunc)(ALfloat *RESTRICT LeftOut, ALfloat *RESTRICT RightOut,
const ALfloat *data, ALsizei Offset, const ALsizei IrSize,
- const ALfloat (*restrict Coeffs)[2],
- ALfloat (*restrict Values)[2], ALsizei BufferSize);
+ const ALfloat (*RESTRICT Coeffs)[2],
+ ALfloat (*RESTRICT Values)[2], ALsizei BufferSize);
#define GAIN_MIX_MAX (16.0f) /* +24dB */
@@ -491,8 +491,8 @@ inline float ScaleAzimuthFront(float azimuth, float scale)
}
-void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
-void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat*RESTRICT coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat*RESTRICT coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
/**
* ComputePanGains
@@ -502,7 +502,7 @@ void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, con
* coeffs are a 'slice' of a transform matrix for the input channel, used to
* scale and orient the sound samples.
*/
-inline void ComputePanGains(const MixParams *dry, const ALfloat*restrict coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+inline void ComputePanGains(const MixParams *dry, const ALfloat*RESTRICT coeffs, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
{
if(dry->CoeffCount > 0)
ComputePanningGainsMC(dry->Ambi.Coeffs, dry->NumChannels, dry->CoeffCount,
diff --git a/OpenAL32/Include/bs2b.h b/OpenAL32/Include/bs2b.h
index e845d906..13cdf9a6 100644
--- a/OpenAL32/Include/bs2b.h
+++ b/OpenAL32/Include/bs2b.h
@@ -85,7 +85,7 @@ int bs2b_get_srate(struct bs2b *bs2b);
/* Clear buffer */
void bs2b_clear(struct bs2b *bs2b);
-void bs2b_cross_feed(struct bs2b *bs2b, float *restrict Left, float *restrict Right, int SamplesToDo);
+void bs2b_cross_feed(struct bs2b *bs2b, float *RESTRICT Left, float *RESTRICT Right, int SamplesToDo);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/OpenAL32/Include/sample_cvt.h b/OpenAL32/Include/sample_cvt.h
index c041760e..a3b53d44 100644
--- a/OpenAL32/Include/sample_cvt.h
+++ b/OpenAL32/Include/sample_cvt.h
@@ -4,6 +4,10 @@
#include "AL/al.h"
#include "alBuffer.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
extern const ALshort muLawDecompressionTable[256];
extern const ALshort aLawDecompressionTable[256];
@@ -12,4 +16,8 @@ void Convert_ALshort_ALima4(ALshort *dst, const ALubyte *src, ALsizei numchans,
void Convert_ALshort_ALmsadpcm(ALshort *dst, const ALubyte *src, ALsizei numchans, ALsizei len,
ALsizei align);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* SAMPLE_CVT_H */
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index 8141e0f6..e1d84bb9 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -116,7 +116,7 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
context = GetContextRef();
if(!context) return;
- if(!(n >= 0))
+ if(n < 0)
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Generating %d effect slots", n);
if(n == 0) goto done;
@@ -179,7 +179,7 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *
if(!context) return;
LockEffectSlotList(context);
- if(!(n >= 0))
+ if(n < 0)
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d effect slots", n);
if(n == 0) goto done;
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.cpp
index ed712434..b33dc584 100644
--- a/OpenAL32/alBuffer.c
+++ b/OpenAL32/alBuffer.cpp
@@ -23,11 +23,15 @@
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
-#include <limits.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
+#include <array>
+#include <vector>
+#include <limits>
+#include <algorithm>
+
#include "alMain.h"
#include "alu.h"
#include "alError.h"
@@ -35,128 +39,484 @@
#include "sample_cvt.h"
-extern inline void LockBufferList(ALCdevice *device);
-extern inline void UnlockBufferList(ALCdevice *device);
-extern inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
-extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
+namespace {
+
+constexpr ALbitfieldSOFT INVALID_STORAGE_MASK{~unsigned(AL_MAP_READ_BIT_SOFT |
+ AL_MAP_WRITE_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT | AL_PRESERVE_DATA_BIT_SOFT)};
+constexpr ALbitfieldSOFT MAP_READ_WRITE_FLAGS{AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT};
+constexpr ALbitfieldSOFT INVALID_MAP_FLAGS{~unsigned(AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT |
+ AL_MAP_PERSISTENT_BIT_SOFT)};
-static ALbuffer *AllocBuffer(ALCcontext *context);
-static void FreeBuffer(ALCdevice *device, ALbuffer *buffer);
-static const ALchar *NameFromUserFmtType(enum UserFmtType type);
-static void LoadData(ALCcontext *context, ALbuffer *buffer, ALuint freq, ALsizei size,
- enum UserFmtChannels SrcChannels, enum UserFmtType SrcType,
- const ALvoid *data, ALbitfieldSOFT access);
-static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type);
-static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align);
-static inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
+ALbuffer *AllocBuffer(ALCcontext *context)
+{
+ ALCdevice *device = context->Device;
+ std::unique_lock<almtx_t> buflock{device->BufferLock};
+
+ ALbuffer *buffer{nullptr};
+ ALsizei lidx{0}, slidx{0};
+ BufferSubList *sublist{VECTOR_BEGIN(device->BufferList)};
+ BufferSubList *subend{VECTOR_END(device->BufferList)};
+ for(;sublist != subend;++sublist)
+ {
+ if(sublist->FreeMask)
+ {
+ slidx = CTZ64(sublist->FreeMask);
+ buffer = sublist->Buffers + slidx;
+ break;
+ }
+ ++lidx;
+ }
+ if(UNLIKELY(!buffer))
+ {
+ static constexpr BufferSubList empty_sublist{ 0, nullptr };
+ /* Don't allocate so many list entries that the 32-bit ID could
+ * overflow...
+ */
+ if(UNLIKELY(VECTOR_SIZE(device->BufferList) >= 1<<25))
+ {
+ buflock.unlock();
+ alSetError(context, AL_OUT_OF_MEMORY, "Too many buffers allocated");
+ return nullptr;
+ }
+ lidx = (ALsizei)VECTOR_SIZE(device->BufferList);
+ VECTOR_PUSH_BACK(device->BufferList, empty_sublist);
+ sublist = &VECTOR_BACK(device->BufferList);
+ sublist->FreeMask = ~U64(0);
+ sublist->Buffers = reinterpret_cast<ALbuffer*>(al_calloc(16, sizeof(ALbuffer)*64));
+ if(UNLIKELY(!sublist->Buffers))
+ {
+ VECTOR_POP_BACK(device->BufferList);
+ buflock.unlock();
+ alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate buffer batch");
+ return nullptr;
+ }
+
+ slidx = 0;
+ buffer = sublist->Buffers + slidx;
+ }
+
+ memset(buffer, 0, sizeof(*buffer));
+
+ /* Add 1 to avoid buffer ID 0. */
+ buffer->id = ((lidx<<6) | slidx) + 1;
+
+ sublist->FreeMask &= ~(U64(1)<<slidx);
+
+ return buffer;
+}
+
+void FreeBuffer(ALCdevice *device, ALbuffer *buffer)
+{
+ ALuint id{buffer->id - 1};
+ ALsizei lidx = id >> 6;
+ ALsizei slidx = id & 0x3f;
+
+ al_free(buffer->data);
+ memset(buffer, 0, sizeof(*buffer));
+
+ VECTOR_ELEM(device->BufferList, lidx).FreeMask |= U64(1) << slidx;
+}
+
+inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
{
- BufferSubList *sublist;
ALuint lidx = (id-1) >> 6;
ALsizei slidx = (id-1) & 0x3f;
if(UNLIKELY(lidx >= VECTOR_SIZE(device->BufferList)))
- return NULL;
- sublist = &VECTOR_ELEM(device->BufferList, lidx);
+ return nullptr;
+ BufferSubList *sublist{&VECTOR_ELEM(device->BufferList, lidx)};
if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
- return NULL;
+ return nullptr;
return sublist->Buffers + slidx;
}
-#define INVALID_STORAGE_MASK ~(AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_PRESERVE_DATA_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT)
-#define MAP_READ_WRITE_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT)
-#define INVALID_MAP_FLAGS ~(AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT)
-
-
-AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
+ALsizei SanitizeAlignment(UserFmtType type, ALsizei align)
{
- ALCcontext *context;
- ALsizei cur = 0;
-
- context = GetContextRef();
- if(!context) return;
+ if(align < 0)
+ return 0;
- if(!(n >= 0))
- alSetError(context, AL_INVALID_VALUE, "Generating %d buffers", n);
- else for(cur = 0;cur < n;cur++)
+ if(align == 0)
{
- ALbuffer *buffer = AllocBuffer(context);
- if(!buffer)
+ if(type == UserFmtIMA4)
{
- alDeleteBuffers(cur, buffers);
- break;
+ /* Here is where things vary:
+ * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
+ * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
+ */
+ return 65;
}
+ if(type == UserFmtMSADPCM)
+ return 64;
+ return 1;
+ }
- buffers[cur] = buffer->id;
+ if(type == UserFmtIMA4)
+ {
+ /* IMA4 block alignment must be a multiple of 8, plus 1. */
+ if((align&7) == 1) return align;
+ return 0;
+ }
+ if(type == UserFmtMSADPCM)
+ {
+ /* MSADPCM block alignment must be a multiple of 2. */
+ if((align&1) == 0) return align;
+ return 0;
}
- ALCcontext_DecRef(context);
+ return align;
}
-AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
+
+const ALchar *NameFromUserFmtType(UserFmtType type)
+{
+ switch(type)
+ {
+ case UserFmtUByte: return "Unsigned Byte";
+ case UserFmtShort: return "Signed Short";
+ case UserFmtFloat: return "Float32";
+ case UserFmtDouble: return "Float64";
+ case UserFmtMulaw: return "muLaw";
+ case UserFmtAlaw: return "aLaw";
+ case UserFmtIMA4: return "IMA4 ADPCM";
+ case UserFmtMSADPCM: return "MSADPCM";
+ }
+ return "<internal type error>";
+}
+
+/*
+ * LoadData
+ *
+ * Loads the specified data into the buffer, using the specified format.
+ */
+void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALuint freq, ALsizei size, UserFmtChannels SrcChannels, UserFmtType SrcType, const ALvoid *data, ALbitfieldSOFT access)
{
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *ALBuf;
- ALsizei i;
+ if(UNLIKELY(ReadRef(&ALBuf->ref) != 0 || ALBuf->MappedAccess != 0))
+ SETERR_RETURN(context, AL_INVALID_OPERATION,, "Modifying storage for in-use buffer %u",
+ ALBuf->id);
- context = GetContextRef();
- if(!context) return;
+ /* Currently no channel configurations need to be converted. */
+ FmtChannels DstChannels{FmtMono};
+ switch(SrcChannels)
+ {
+ case UserFmtMono: DstChannels = FmtMono; break;
+ case UserFmtStereo: DstChannels = FmtStereo; break;
+ case UserFmtRear: DstChannels = FmtRear; break;
+ case UserFmtQuad: DstChannels = FmtQuad; break;
+ case UserFmtX51: DstChannels = FmtX51; break;
+ case UserFmtX61: DstChannels = FmtX61; break;
+ case UserFmtX71: DstChannels = FmtX71; break;
+ case UserFmtBFormat2D: DstChannels = FmtBFormat2D; break;
+ case UserFmtBFormat3D: DstChannels = FmtBFormat3D; break;
+ }
+ if(UNLIKELY((long)SrcChannels != (long)DstChannels))
+ SETERR_RETURN(context, AL_INVALID_ENUM,, "Invalid format");
- device = context->Device;
+ /* IMA4 and MSADPCM convert to 16-bit short. */
+ FmtType DstType{FmtUByte};
+ switch(SrcType)
+ {
+ case UserFmtUByte: DstType = FmtUByte; break;
+ case UserFmtShort: DstType = FmtShort; break;
+ case UserFmtFloat: DstType = FmtFloat; break;
+ case UserFmtDouble: DstType = FmtDouble; break;
+ case UserFmtAlaw: DstType = FmtAlaw; break;
+ case UserFmtMulaw: DstType = FmtMulaw; break;
+ case UserFmtIMA4: DstType = FmtShort; break;
+ case UserFmtMSADPCM: DstType = FmtShort; break;
+ }
- LockBufferList(device);
- if(UNLIKELY(n < 0))
+ /* TODO: Currently we can only map samples when they're not converted. To
+ * allow it would need some kind of double-buffering to hold onto a copy of
+ * the original data.
+ */
+ if((access&MAP_READ_WRITE_FLAGS))
{
- alSetError(context, AL_INVALID_VALUE, "Deleting %d buffers", n);
- goto done;
+ if(UNLIKELY((long)SrcType != (long)DstType))
+ SETERR_RETURN(context, AL_INVALID_VALUE,, "%s samples cannot be mapped",
+ NameFromUserFmtType(SrcType));
}
- for(i = 0;i < n;i++)
+ ALsizei unpackalign{ATOMIC_LOAD_SEQ(&ALBuf->UnpackAlign)};
+ ALsizei align{SanitizeAlignment(SrcType, unpackalign)};
+ if(UNLIKELY(align < 1))
+ SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid unpack alignment %d for %s samples",
+ unpackalign, NameFromUserFmtType(SrcType));
+
+ if((access&AL_PRESERVE_DATA_BIT_SOFT))
{
- if(!buffers[i])
- continue;
+ /* Can only preserve data with the same format and alignment. */
+ if(UNLIKELY(ALBuf->FmtChannels != DstChannels || ALBuf->OriginalType != SrcType))
+ SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched format");
+ if(UNLIKELY(ALBuf->OriginalAlign != align))
+ SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched alignment");
+ }
+
+ /* Convert the input/source size in bytes to sample frames using the unpack
+ * block alignment.
+ */
+ ALsizei SrcByteAlign{
+ (SrcType == UserFmtIMA4) ? ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels) :
+ (SrcType == UserFmtMSADPCM) ? ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels) :
+ align * FrameSizeFromUserFmt(SrcChannels, SrcType)
+ };
+ if(UNLIKELY((size%SrcByteAlign) != 0))
+ SETERR_RETURN(context, AL_INVALID_VALUE,,
+ "Data size %d is not a multiple of frame size %d (%d unpack alignment)",
+ size, SrcByteAlign, align);
+
+ if(UNLIKELY(size/SrcByteAlign > std::numeric_limits<ALsizei>::max()/align))
+ SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
+ "Buffer size overflow, %d blocks x %d samples per block", size/SrcByteAlign, align);
+ ALsizei frames{size / SrcByteAlign * align};
+
+ /* Convert the sample frames to the number of bytes needed for internal
+ * storage.
+ */
+ ALsizei NumChannels{ChannelsFromFmt(DstChannels)};
+ ALsizei FrameSize{NumChannels * BytesFromFmt(DstType)};
+ if(UNLIKELY(frames > std::numeric_limits<ALsizei>::max()/FrameSize))
+ SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
+ "Buffer size overflow, %d frames x %d bytes per frame", frames, FrameSize);
+ ALsizei newsize{frames*FrameSize};
- /* Check for valid Buffer ID, and make sure it's not in use. */
- if((ALBuf=LookupBuffer(device, buffers[i])) == NULL)
+ /* Round up to the next 16-byte multiple. This could reallocate only when
+ * increasing or the new size is less than half the current, but then the
+ * buffer's AL_SIZE would not be very reliable for accounting buffer memory
+ * usage, and reporting the real size could cause problems for apps that
+ * use AL_SIZE to try to get the buffer's play length.
+ */
+ if(LIKELY(newsize <= std::numeric_limits<ALsizei>::max()-15))
+ newsize = (newsize+15) & ~0xf;
+ if(newsize != ALBuf->BytesAlloc)
+ {
+ void *temp{al_malloc(16, (size_t)newsize)};
+ if(UNLIKELY(!temp && newsize))
+ SETERR_RETURN(context, AL_OUT_OF_MEMORY,, "Failed to allocate %d bytes of storage",
+ newsize);
+ if((access&AL_PRESERVE_DATA_BIT_SOFT))
{
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffers[i]);
- goto done;
+ ALsizei tocopy{std::min(newsize, ALBuf->BytesAlloc)};
+ if(tocopy > 0) memcpy(temp, ALBuf->data, tocopy);
}
- if(ReadRef(&ALBuf->ref) != 0)
+ al_free(ALBuf->data);
+ ALBuf->data = temp;
+ ALBuf->BytesAlloc = newsize;
+ }
+
+ if(SrcType == UserFmtIMA4)
+ {
+ assert(DstType == FmtShort);
+ if(data != nullptr && ALBuf->data != nullptr)
+ Convert_ALshort_ALima4(static_cast<ALshort*>(ALBuf->data),
+ static_cast<const ALubyte*>(data), NumChannels, frames, align);
+ ALBuf->OriginalAlign = align;
+ }
+ else if(SrcType == UserFmtMSADPCM)
+ {
+ assert(DstType == FmtShort);
+ if(data != nullptr && ALBuf->data != nullptr)
+ Convert_ALshort_ALmsadpcm(static_cast<ALshort*>(ALBuf->data),
+ static_cast<const ALubyte*>(data), NumChannels, frames, align);
+ ALBuf->OriginalAlign = align;
+ }
+ else
+ {
+ assert((long)SrcType == (long)DstType);
+ if(data != nullptr && ALBuf->data != nullptr)
+ memcpy(ALBuf->data, data, frames*FrameSize);
+ ALBuf->OriginalAlign = 1;
+ }
+ ALBuf->OriginalSize = size;
+ ALBuf->OriginalType = SrcType;
+
+ ALBuf->Frequency = freq;
+ ALBuf->FmtChannels = DstChannels;
+ ALBuf->FmtType = DstType;
+ ALBuf->Access = access;
+
+ ALBuf->SampleLen = frames;
+ ALBuf->LoopStart = 0;
+ ALBuf->LoopEnd = ALBuf->SampleLen;
+}
+
+ALboolean DecomposeUserFormat(ALenum format, UserFmtChannels *chans, UserFmtType *type)
+{
+ struct FormatMap {
+ ALenum format;
+ UserFmtChannels channels;
+ UserFmtType type;
+ };
+ static constexpr std::array<FormatMap,46> list{{
+ { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
+ { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
+ { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
+ { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
+ { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
+ { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
+ { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
+ { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
+
+ { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
+ { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
+ { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
+ { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
+ { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
+ { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
+ { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
+ { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
+
+ { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
+ { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
+ { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat },
+ { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
+
+ { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte },
+ { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
+
+ { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte },
+ { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort },
+ { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat },
+ { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
+
+ { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte },
+ { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort },
+ { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat },
+ { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
+
+ { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte },
+ { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort },
+ { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat },
+ { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
+
+ { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte },
+ { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort },
+ { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat },
+ { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
+
+ { AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte },
+ { AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort },
+ { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
+ { AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw },
+
+ { AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte },
+ { AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort },
+ { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
+ { AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
+ }};
+
+ for(const auto &fmt : list)
+ {
+ if(fmt.format == format)
{
- alSetError(context, AL_INVALID_OPERATION, "Deleting in-use buffer %u", buffers[i]);
- goto done;
+ *chans = fmt.channels;
+ *type = fmt.type;
+ return AL_TRUE;
}
}
- for(i = 0;i < n;i++)
+
+ return AL_FALSE;
+}
+
+} // namespace
+
+
+AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
+{
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
+
+ if(UNLIKELY(n < 0))
+ {
+ alSetError(context.get(), AL_INVALID_VALUE, "Generating %d buffers", n);
+ return;
+ }
+
+ if(LIKELY(n == 1))
{
- if((ALBuf=LookupBuffer(device, buffers[i])) != NULL)
- FreeBuffer(device, ALBuf);
+ /* Special handling for the easy and normal case. */
+ ALbuffer *buffer = AllocBuffer(context.get());
+ if(buffer) buffers[0] = buffer->id;
}
+ else if(n > 1)
+ {
+ /* Store the allocated buffer IDs in a separate local list, to avoid
+ * modifying the user storage in case of failure.
+ */
+ std::vector<ALuint> ids;
+ ids.reserve(n);
+ do {
+ ALbuffer *buffer = AllocBuffer(context.get());
+ if(!buffer)
+ {
+ alDeleteBuffers(ids.size(), ids.data());
+ return;
+ }
-done:
- UnlockBufferList(device);
- ALCcontext_DecRef(context);
+ ids.emplace_back(buffer->id);
+ } while(--n);
+ std::copy(ids.begin(), ids.end(), buffers);
+ }
}
-AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
+AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
{
- ALCcontext *context;
- ALboolean ret;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return AL_FALSE;
+ if(UNLIKELY(n < 0))
+ {
+ alSetError(context.get(), AL_INVALID_VALUE, "Deleting %d buffers", n);
+ return;
+ }
+ if(UNLIKELY(n == 0))
+ return;
- LockBufferList(context->Device);
- ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
- AL_TRUE : AL_FALSE);
- UnlockBufferList(context->Device);
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- ALCcontext_DecRef(context);
+ /* First try to find any buffers that are invalid or in-use. */
+ const ALuint *buffers_end = buffers + n;
+ auto invbuf = std::find_if(buffers, buffers_end,
+ [device, &context](ALuint bid) -> bool
+ {
+ if(!bid) return false;
+ ALbuffer *ALBuf = LookupBuffer(device, bid);
+ if(UNLIKELY(!ALBuf))
+ {
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", bid);
+ return true;
+ }
+ if(UNLIKELY(ReadRef(&ALBuf->ref) != 0))
+ {
+ alSetError(context.get(), AL_INVALID_OPERATION, "Deleting in-use buffer %u", bid);
+ return true;
+ }
+ return false;
+ }
+ );
+ if(LIKELY(invbuf == buffers_end))
+ {
+ /* All good. Delete non-0 buffer IDs. */
+ std::for_each(buffers, buffers_end,
+ [device](ALuint bid) -> void
+ { if(bid) FreeBuffer(device, LookupBuffer(device, bid)); }
+ );
+ }
+}
- return ret;
+AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
+{
+ ContextRef context{GetContextRef()};
+ if(LIKELY(context))
+ {
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
+ if(!buffer || LookupBuffer(device, buffer))
+ return AL_TRUE;
+ }
+ return AL_FALSE;
}
@@ -165,138 +525,123 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags)
{
- enum UserFmtChannels srcchannels = UserFmtMono;
- enum UserFmtType srctype = UserFmtUByte;
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
-
- context = GetContextRef();
- if(!context) return;
-
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
+
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
+
+ UserFmtChannels srcchannels{UserFmtMono};
+ UserFmtType srctype{UserFmtUByte};
+
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(size < 0))
- alSetError(context, AL_INVALID_VALUE, "Negative storage size %d", size);
+ alSetError(context.get(), AL_INVALID_VALUE, "Negative storage size %d", size);
else if(UNLIKELY(freq < 1))
- alSetError(context, AL_INVALID_VALUE, "Invalid sample rate %d", freq);
+ alSetError(context.get(), AL_INVALID_VALUE, "Invalid sample rate %d", freq);
else if(UNLIKELY((flags&INVALID_STORAGE_MASK) != 0))
- alSetError(context, AL_INVALID_VALUE, "Invalid storage flags 0x%x",
+ alSetError(context.get(), AL_INVALID_VALUE, "Invalid storage flags 0x%x",
flags&INVALID_STORAGE_MASK);
else if(UNLIKELY((flags&AL_MAP_PERSISTENT_BIT_SOFT) && !(flags&MAP_READ_WRITE_FLAGS)))
- alSetError(context, AL_INVALID_VALUE,
+ alSetError(context.get(), AL_INVALID_VALUE,
"Declaring persistently mapped storage without read or write access");
else if(UNLIKELY(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE))
- alSetError(context, AL_INVALID_ENUM, "Invalid format 0x%04x", format);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid format 0x%04x", format);
else
- LoadData(context, albuf, freq, size, srcchannels, srctype, data, flags);
-
- UnlockBufferList(device);
- ALCcontext_DecRef(context);
+ LoadData(context.get(), albuf, freq, size, srcchannels, srctype, data, flags);
}
AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access)
{
- void *retval = NULL;
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
-
- context = GetContextRef();
- if(!context) return retval;
-
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return nullptr;
+
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
+
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY((access&INVALID_MAP_FLAGS) != 0))
- alSetError(context, AL_INVALID_VALUE, "Invalid map flags 0x%x", access&INVALID_MAP_FLAGS);
+ alSetError(context.get(), AL_INVALID_VALUE, "Invalid map flags 0x%x", access&INVALID_MAP_FLAGS);
else if(UNLIKELY(!(access&MAP_READ_WRITE_FLAGS)))
- alSetError(context, AL_INVALID_VALUE, "Mapping buffer %u without read or write access",
+ alSetError(context.get(), AL_INVALID_VALUE, "Mapping buffer %u without read or write access",
buffer);
else
{
ALbitfieldSOFT unavailable = (albuf->Access^access) & access;
if(UNLIKELY(ReadRef(&albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)))
- alSetError(context, AL_INVALID_OPERATION,
+ alSetError(context.get(), AL_INVALID_OPERATION,
"Mapping in-use buffer %u without persistent mapping", buffer);
else if(UNLIKELY(albuf->MappedAccess != 0))
- alSetError(context, AL_INVALID_OPERATION, "Mapping already-mapped buffer %u", buffer);
+ alSetError(context.get(), AL_INVALID_OPERATION, "Mapping already-mapped buffer %u", buffer);
else if(UNLIKELY((unavailable&AL_MAP_READ_BIT_SOFT)))
- alSetError(context, AL_INVALID_VALUE,
+ alSetError(context.get(), AL_INVALID_VALUE,
"Mapping buffer %u for reading without read access", buffer);
else if(UNLIKELY((unavailable&AL_MAP_WRITE_BIT_SOFT)))
- alSetError(context, AL_INVALID_VALUE,
+ alSetError(context.get(), AL_INVALID_VALUE,
"Mapping buffer %u for writing without write access", buffer);
else if(UNLIKELY((unavailable&AL_MAP_PERSISTENT_BIT_SOFT)))
- alSetError(context, AL_INVALID_VALUE,
+ alSetError(context.get(), AL_INVALID_VALUE,
"Mapping buffer %u persistently without persistent access", buffer);
else if(UNLIKELY(offset < 0 || offset >= albuf->OriginalSize ||
length <= 0 || length > albuf->OriginalSize - offset))
- alSetError(context, AL_INVALID_VALUE, "Mapping invalid range %d+%d for buffer %u",
+ alSetError(context.get(), AL_INVALID_VALUE, "Mapping invalid range %d+%d for buffer %u",
offset, length, buffer);
else
{
- retval = (ALbyte*)albuf->data + offset;
+ void *retval = (ALbyte*)albuf->data + offset;
albuf->MappedAccess = access;
albuf->MappedOffset = offset;
albuf->MappedSize = length;
+ return retval;
}
}
- UnlockBufferList(device);
- ALCcontext_DecRef(context);
- return retval;
+ return nullptr;
}
AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
{
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if((albuf=LookupBuffer(device, buffer)) == NULL)
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(albuf->MappedAccess == 0)
- alSetError(context, AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer);
+ alSetError(context.get(), AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer);
else
{
albuf->MappedAccess = 0;
albuf->MappedOffset = 0;
albuf->MappedSize = 0;
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length)
{
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)))
- alSetError(context, AL_INVALID_OPERATION,
+ alSetError(context.get(), AL_INVALID_OPERATION,
"Flushing buffer %u while not mapped for writing", buffer);
else if(UNLIKELY(offset < albuf->MappedOffset ||
offset >= albuf->MappedOffset+albuf->MappedSize ||
length <= 0 || length > albuf->MappedOffset+albuf->MappedSize-offset))
- alSetError(context, AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u",
+ alSetError(context.get(), AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u",
offset, length, buffer);
else
{
@@ -307,49 +652,44 @@ AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, A
*/
ATOMIC_THREAD_FENCE(almemory_order_seq_cst);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
{
- enum UserFmtChannels srcchannels = UserFmtMono;
- enum UserFmtType srctype = UserFmtUByte;
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
-
- context = GetContextRef();
- if(!context) return;
-
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
+
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
+
+ UserFmtChannels srcchannels{UserFmtMono};
+ UserFmtType srctype{UserFmtUByte};
+
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE))
- alSetError(context, AL_INVALID_ENUM, "Invalid format 0x%04x", format);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid format 0x%04x", format);
else
{
ALsizei unpack_align, align;
ALsizei byte_align;
ALsizei frame_size;
ALsizei num_chans;
- void *dst;
unpack_align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
align = SanitizeAlignment(srctype, unpack_align);
if(UNLIKELY(align < 1))
- alSetError(context, AL_INVALID_VALUE, "Invalid unpack alignment %d", unpack_align);
+ alSetError(context.get(), AL_INVALID_VALUE, "Invalid unpack alignment %d", unpack_align);
else if(UNLIKELY((long)srcchannels != (long)albuf->FmtChannels ||
srctype != albuf->OriginalType))
- alSetError(context, AL_INVALID_ENUM, "Unpacking data with mismatched format");
+ alSetError(context.get(), AL_INVALID_ENUM, "Unpacking data with mismatched format");
else if(UNLIKELY(align != albuf->OriginalAlign))
- alSetError(context, AL_INVALID_VALUE,
+ alSetError(context.get(), AL_INVALID_VALUE,
"Unpacking data with alignment %u does not match original alignment %u",
align, albuf->OriginalAlign);
else if(UNLIKELY(albuf->MappedAccess != 0))
- alSetError(context, AL_INVALID_OPERATION, "Unpacking data into mapped buffer %u",
+ alSetError(context.get(), AL_INVALID_OPERATION, "Unpacking data into mapped buffer %u",
buffer);
else
{
@@ -364,14 +704,14 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
if(UNLIKELY(offset < 0 || length < 0 || offset > albuf->OriginalSize ||
length > albuf->OriginalSize-offset))
- alSetError(context, AL_INVALID_VALUE, "Invalid data sub-range %d+%d on buffer %u",
+ alSetError(context.get(), AL_INVALID_VALUE, "Invalid data sub-range %d+%d on buffer %u",
offset, length, buffer);
else if(UNLIKELY((offset%byte_align) != 0))
- alSetError(context, AL_INVALID_VALUE,
+ alSetError(context.get(), AL_INVALID_VALUE,
"Sub-range offset %d is not a multiple of frame size %d (%d unpack alignment)",
offset, byte_align, align);
else if(UNLIKELY((length%byte_align) != 0))
- alSetError(context, AL_INVALID_VALUE,
+ alSetError(context.get(), AL_INVALID_VALUE,
"Sub-range length %d is not a multiple of frame size %d (%d unpack alignment)",
length, byte_align, align);
else
@@ -380,11 +720,13 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
offset = offset/byte_align * align * frame_size;
length = length/byte_align * align;
- dst = (ALbyte*)albuf->data + offset;
+ void *dst = static_cast<ALbyte*>(albuf->data) + offset;
if(srctype == UserFmtIMA4 && albuf->FmtType == FmtShort)
- Convert_ALshort_ALima4(dst, data, num_chans, length, align);
+ Convert_ALshort_ALima4(static_cast<ALshort*>(dst),
+ static_cast<const ALubyte*>(data), num_chans, length, align);
else if(srctype == UserFmtMSADPCM && albuf->FmtType == FmtShort)
- Convert_ALshort_ALmsadpcm(dst, data, num_chans, length, align);
+ Convert_ALshort_ALmsadpcm(static_cast<ALshort*>(dst),
+ static_cast<const ALubyte*>(data), num_chans, length, align);
else
{
assert((long)srctype == (long)albuf->FmtType);
@@ -393,9 +735,6 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
}
}
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
@@ -403,224 +742,181 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint UNUSED(buffer),
ALuint UNUSED(samplerate), ALenum UNUSED(internalformat), ALsizei UNUSED(samples),
ALenum UNUSED(channels), ALenum UNUSED(type), const ALvoid *UNUSED(data))
{
- ALCcontext *context;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
-
- alSetError(context, AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported");
-
- ALCcontext_DecRef(context);
+ alSetError(context.get(), AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported");
}
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint UNUSED(buffer),
ALsizei UNUSED(offset), ALsizei UNUSED(samples),
ALenum UNUSED(channels), ALenum UNUSED(type), const ALvoid *UNUSED(data))
{
- ALCcontext *context;
-
- context = GetContextRef();
- if(!context) return;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- alSetError(context, AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported");
-
- ALCcontext_DecRef(context);
+ alSetError(context.get(), AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported");
}
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint UNUSED(buffer),
ALsizei UNUSED(offset), ALsizei UNUSED(samples),
ALenum UNUSED(channels), ALenum UNUSED(type), ALvoid *UNUSED(data))
{
- ALCcontext *context;
-
- context = GetContextRef();
- if(!context) return;
-
- alSetError(context, AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported");
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- ALCcontext_DecRef(context);
+ alSetError(context.get(), AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported");
}
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum UNUSED(format))
{
- ALCcontext *context;
-
- context = GetContextRef();
+ ContextRef context{GetContextRef()};
if(!context) return AL_FALSE;
- alSetError(context, AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported");
-
- ALCcontext_DecRef(context);
+ alSetError(context.get(), AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported");
return AL_FALSE;
}
AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value))
{
- ALCdevice *device;
- ALCcontext *context;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ if(UNLIKELY(LookupBuffer(device, buffer) == nullptr))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
{
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3))
{
- ALCdevice *device;
- ALCcontext *context;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ if(UNLIKELY(LookupBuffer(device, buffer) == nullptr))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
{
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values)
{
- ALCdevice *device;
- ALCcontext *context;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ if(UNLIKELY(LookupBuffer(device, buffer) == nullptr))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!values))
- alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
{
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
{
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
if(UNLIKELY(value < 0))
- alSetError(context, AL_INVALID_VALUE, "Invalid unpack block alignment %d", value);
+ alSetError(context.get(), AL_INVALID_VALUE, "Invalid unpack block alignment %d", value);
else
ATOMIC_STORE_SEQ(&albuf->UnpackAlign, value);
break;
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
if(UNLIKELY(value < 0))
- alSetError(context, AL_INVALID_VALUE, "Invalid pack block alignment %d", value);
+ alSetError(context.get(), AL_INVALID_VALUE, "Invalid pack block alignment %d", value);
else
ATOMIC_STORE_SEQ(&albuf->PackAlign, value);
break;
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3))
{
- ALCdevice *device;
- ALCcontext *context;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ if(UNLIKELY(LookupBuffer(device, buffer) == nullptr))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
{
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values)
{
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
-
if(values)
{
switch(param)
{
- case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
- case AL_PACK_BLOCK_ALIGNMENT_SOFT:
- alBufferi(buffer, param, values[0]);
- return;
+ case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+ case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+ alBufferi(buffer, param, values[0]);
+ return;
}
}
- context = GetContextRef();
- if(!context) return;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
+
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!values))
- alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
case AL_LOOP_POINTS_SOFT:
if(UNLIKELY(ReadRef(&albuf->ref) != 0))
- alSetError(context, AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points",
+ alSetError(context.get(), AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points",
buffer);
else if(UNLIKELY(values[0] >= values[1] || values[0] < 0 || values[1] > albuf->SampleLen))
- alSetError(context, AL_INVALID_VALUE, "Invalid loop point range %d -> %d o buffer %u",
+ alSetError(context.get(), AL_INVALID_VALUE, "Invalid loop point range %d -> %d o buffer %u",
values[0], values[1], buffer);
else
{
@@ -630,71 +926,55 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *val
break;
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x",
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x",
param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value)
{
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!value))
- alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
{
- ALCdevice *device;
- ALCcontext *context;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ if(UNLIKELY(LookupBuffer(device, buffer) == nullptr))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!value1 || !value2 || !value3))
- alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values)
{
- ALCdevice *device;
- ALCcontext *context;
-
switch(param)
{
case AL_SEC_LENGTH_SOFT:
@@ -702,41 +982,37 @@ AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *valu
return;
}
- context = GetContextRef();
- if(!context) return;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
+
+ if(UNLIKELY(LookupBuffer(device, buffer) == nullptr))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!values))
- alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
{
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!value))
- alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
case AL_FREQUENCY:
@@ -765,45 +1041,33 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
break;
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3)
{
- ALCdevice *device;
- ALCcontext *context;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- context = GetContextRef();
- if(!context) return;
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ if(UNLIKELY(LookupBuffer(device, buffer) == nullptr))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!value1 || !value2 || !value3))
- alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values)
{
- ALCdevice *device;
- ALCcontext *context;
- ALbuffer *albuf;
-
switch(param)
{
case AL_FREQUENCY:
@@ -819,15 +1083,17 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values
return;
}
- context = GetContextRef();
- if(!context) return;
+ ContextRef context{GetContextRef()};
+ if(UNLIKELY(!context)) return;
- device = context->Device;
- LockBufferList(device);
- if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
- alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
+ ALCdevice *device = context->Device;
+ std::lock_guard<almtx_t> _{device->BufferLock};
+
+ ALbuffer *albuf = LookupBuffer(device, buffer);
+ if(UNLIKELY(!albuf))
+ alSetError(context.get(), AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!values))
- alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
case AL_LOOP_POINTS_SOFT:
@@ -836,194 +1102,13 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values
break;
default:
- alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x",
+ alSetError(context.get(), AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x",
param);
}
- UnlockBufferList(device);
-
- ALCcontext_DecRef(context);
}
-static const ALchar *NameFromUserFmtType(enum UserFmtType type)
-{
- switch(type)
- {
- case UserFmtUByte: return "Unsigned Byte";
- case UserFmtShort: return "Signed Short";
- case UserFmtFloat: return "Float32";
- case UserFmtDouble: return "Float64";
- case UserFmtMulaw: return "muLaw";
- case UserFmtAlaw: return "aLaw";
- case UserFmtIMA4: return "IMA4 ADPCM";
- case UserFmtMSADPCM: return "MSADPCM";
- }
- return "<internal type error>";
-}
-
-/*
- * LoadData
- *
- * Loads the specified data into the buffer, using the specified format.
- */
-static void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALuint freq, ALsizei size, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALbitfieldSOFT access)
-{
- enum FmtChannels DstChannels = FmtMono;
- enum FmtType DstType = FmtUByte;
- ALsizei NumChannels, FrameSize;
- ALsizei SrcByteAlign;
- ALsizei unpackalign;
- ALsizei newsize;
- ALsizei frames;
- ALsizei align;
-
- if(UNLIKELY(ReadRef(&ALBuf->ref) != 0 || ALBuf->MappedAccess != 0))
- SETERR_RETURN(context, AL_INVALID_OPERATION,, "Modifying storage for in-use buffer %u",
- ALBuf->id);
-
- /* Currently no channel configurations need to be converted. */
- switch(SrcChannels)
- {
- case UserFmtMono: DstChannels = FmtMono; break;
- case UserFmtStereo: DstChannels = FmtStereo; break;
- case UserFmtRear: DstChannels = FmtRear; break;
- case UserFmtQuad: DstChannels = FmtQuad; break;
- case UserFmtX51: DstChannels = FmtX51; break;
- case UserFmtX61: DstChannels = FmtX61; break;
- case UserFmtX71: DstChannels = FmtX71; break;
- case UserFmtBFormat2D: DstChannels = FmtBFormat2D; break;
- case UserFmtBFormat3D: DstChannels = FmtBFormat3D; break;
- }
- if(UNLIKELY((long)SrcChannels != (long)DstChannels))
- SETERR_RETURN(context, AL_INVALID_ENUM,, "Invalid format");
-
- /* IMA4 and MSADPCM convert to 16-bit short. */
- switch(SrcType)
- {
- case UserFmtUByte: DstType = FmtUByte; break;
- case UserFmtShort: DstType = FmtShort; break;
- case UserFmtFloat: DstType = FmtFloat; break;
- case UserFmtDouble: DstType = FmtDouble; break;
- case UserFmtAlaw: DstType = FmtAlaw; break;
- case UserFmtMulaw: DstType = FmtMulaw; break;
- case UserFmtIMA4: DstType = FmtShort; break;
- case UserFmtMSADPCM: DstType = FmtShort; break;
- }
-
- /* TODO: Currently we can only map samples when they're not converted. To
- * allow it would need some kind of double-buffering to hold onto a copy of
- * the original data.
- */
- if((access&MAP_READ_WRITE_FLAGS))
- {
- if(UNLIKELY((long)SrcType != (long)DstType))
- SETERR_RETURN(context, AL_INVALID_VALUE,, "%s samples cannot be mapped",
- NameFromUserFmtType(SrcType));
- }
-
- unpackalign = ATOMIC_LOAD_SEQ(&ALBuf->UnpackAlign);
- if(UNLIKELY((align=SanitizeAlignment(SrcType, unpackalign)) < 1))
- SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid unpack alignment %d for %s samples",
- unpackalign, NameFromUserFmtType(SrcType));
-
- if((access&AL_PRESERVE_DATA_BIT_SOFT))
- {
- /* Can only preserve data with the same format and alignment. */
- if(UNLIKELY(ALBuf->FmtChannels != DstChannels || ALBuf->OriginalType != SrcType))
- SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched format");
- if(UNLIKELY(ALBuf->OriginalAlign != align))
- SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched alignment");
- }
-
- /* Convert the input/source size in bytes to sample frames using the unpack
- * block alignment.
- */
- if(SrcType == UserFmtIMA4)
- SrcByteAlign = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
- else if(SrcType == UserFmtMSADPCM)
- SrcByteAlign = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
- else
- SrcByteAlign = align * FrameSizeFromUserFmt(SrcChannels, SrcType);
- if(UNLIKELY((size%SrcByteAlign) != 0))
- SETERR_RETURN(context, AL_INVALID_VALUE,,
- "Data size %d is not a multiple of frame size %d (%d unpack alignment)",
- size, SrcByteAlign, align);
-
- if(UNLIKELY(size / SrcByteAlign > INT_MAX / align))
- SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
- "Buffer size overflow, %d blocks x %d samples per block", size/SrcByteAlign, align);
- frames = size / SrcByteAlign * align;
-
- /* Convert the sample frames to the number of bytes needed for internal
- * storage.
- */
- NumChannels = ChannelsFromFmt(DstChannels);
- FrameSize = NumChannels * BytesFromFmt(DstType);
- if(UNLIKELY(frames > INT_MAX/FrameSize))
- SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
- "Buffer size overflow, %d frames x %d bytes per frame", frames, FrameSize);
- newsize = frames*FrameSize;
-
- /* Round up to the next 16-byte multiple. This could reallocate only when
- * increasing or the new size is less than half the current, but then the
- * buffer's AL_SIZE would not be very reliable for accounting buffer memory
- * usage, and reporting the real size could cause problems for apps that
- * use AL_SIZE to try to get the buffer's play length.
- */
- if(LIKELY(newsize <= INT_MAX-15))
- newsize = (newsize+15) & ~0xf;
- if(newsize != ALBuf->BytesAlloc)
- {
- void *temp = al_malloc(16, (size_t)newsize);
- if(UNLIKELY(!temp && newsize))
- SETERR_RETURN(context, AL_OUT_OF_MEMORY,, "Failed to allocate %d bytes of storage",
- newsize);
- if((access&AL_PRESERVE_DATA_BIT_SOFT))
- {
- ALsizei tocopy = mini(newsize, ALBuf->BytesAlloc);
- if(tocopy > 0) memcpy(temp, ALBuf->data, tocopy);
- }
- al_free(ALBuf->data);
- ALBuf->data = temp;
- ALBuf->BytesAlloc = newsize;
- }
-
- if(SrcType == UserFmtIMA4)
- {
- assert(DstType == FmtShort);
- if(data != NULL && ALBuf->data != NULL)
- Convert_ALshort_ALima4(ALBuf->data, data, NumChannels, frames, align);
- ALBuf->OriginalAlign = align;
- }
- else if(SrcType == UserFmtMSADPCM)
- {
- assert(DstType == FmtShort);
- if(data != NULL && ALBuf->data != NULL)
- Convert_ALshort_ALmsadpcm(ALBuf->data, data, NumChannels, frames, align);
- ALBuf->OriginalAlign = align;
- }
- else
- {
- assert((long)SrcType == (long)DstType);
- if(data != NULL && ALBuf->data != NULL)
- memcpy(ALBuf->data, data, frames*FrameSize);
- ALBuf->OriginalAlign = 1;
- }
- ALBuf->OriginalSize = size;
- ALBuf->OriginalType = SrcType;
-
- ALBuf->Frequency = freq;
- ALBuf->FmtChannels = DstChannels;
- ALBuf->FmtType = DstType;
- ALBuf->Access = access;
-
- ALBuf->SampleLen = frames;
- ALBuf->LoopStart = 0;
- ALBuf->LoopEnd = ALBuf->SampleLen;
-}
-
-
-ALsizei BytesFromUserFmt(enum UserFmtType type)
+ALsizei BytesFromUserFmt(UserFmtType type)
{
switch(type)
{
@@ -1038,7 +1123,7 @@ ALsizei BytesFromUserFmt(enum UserFmtType type)
}
return 0;
}
-ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans)
+ALsizei ChannelsFromUserFmt(UserFmtChannels chans)
{
switch(chans)
{
@@ -1054,86 +1139,8 @@ ALsizei ChannelsFromUserFmt(enum UserFmtChannels chans)
}
return 0;
}
-static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
- enum UserFmtType *type)
-{
- static const struct {
- ALenum format;
- enum UserFmtChannels channels;
- enum UserFmtType type;
- } list[] = {
- { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
- { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
- { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
- { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
- { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
- { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
- { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
- { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
-
- { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
- { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
- { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
- { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
- { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
- { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
- { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
- { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
-
- { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
- { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
- { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat },
- { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
-
- { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte },
- { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
-
- { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte },
- { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort },
- { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat },
- { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
-
- { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte },
- { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort },
- { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat },
- { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
-
- { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte },
- { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort },
- { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat },
- { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
-
- { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte },
- { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort },
- { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat },
- { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
-
- { AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte },
- { AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort },
- { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
- { AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw },
-
- { AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte },
- { AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort },
- { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
- { AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw },
- };
- ALuint i;
-
- for(i = 0;i < COUNTOF(list);i++)
- {
- if(list[i].format == format)
- {
- *chans = list[i].channels;
- *type = list[i].type;
- return AL_TRUE;
- }
- }
-
- return AL_FALSE;
-}
-ALsizei BytesFromFmt(enum FmtType type)
+ALsizei BytesFromFmt(FmtType type)
{
switch(type)
{
@@ -1146,7 +1153,7 @@ ALsizei BytesFromFmt(enum FmtType type)
}
return 0;
}
-ALsizei ChannelsFromFmt(enum FmtChannels chans)
+ALsizei ChannelsFromFmt(FmtChannels chans)
{
switch(chans)
{
@@ -1163,116 +1170,6 @@ ALsizei ChannelsFromFmt(enum FmtChannels chans)
return 0;
}
-static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align)
-{
- if(align < 0)
- return 0;
-
- if(align == 0)
- {
- if(type == UserFmtIMA4)
- {
- /* Here is where things vary:
- * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
- * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
- */
- return 65;
- }
- if(type == UserFmtMSADPCM)
- return 64;
- return 1;
- }
-
- if(type == UserFmtIMA4)
- {
- /* IMA4 block alignment must be a multiple of 8, plus 1. */
- if((align&7) == 1) return align;
- return 0;
- }
- if(type == UserFmtMSADPCM)
- {
- /* MSADPCM block alignment must be a multiple of 2. */
- if((align&1) == 0) return align;
- return 0;
- }
-
- return align;
-}
-
-
-static ALbuffer *AllocBuffer(ALCcontext *context)
-{
- ALCdevice *device = context->Device;
- BufferSubList *sublist, *subend;
- ALbuffer *buffer = NULL;
- ALsizei lidx = 0;
- ALsizei slidx;
-
- almtx_lock(&device->BufferLock);
- sublist = VECTOR_BEGIN(device->BufferList);
- subend = VECTOR_END(device->BufferList);
- for(;sublist != subend;++sublist)
- {
- if(sublist->FreeMask)
- {
- slidx = CTZ64(sublist->FreeMask);
- buffer = sublist->Buffers + slidx;
- break;
- }
- ++lidx;
- }
- if(UNLIKELY(!buffer))
- {
- const BufferSubList empty_sublist = { 0, NULL };
- /* Don't allocate so many list entries that the 32-bit ID could
- * overflow...
- */
- if(UNLIKELY(VECTOR_SIZE(device->BufferList) >= 1<<25))
- {
- almtx_unlock(&device->BufferLock);
- alSetError(context, AL_OUT_OF_MEMORY, "Too many buffers allocated");
- return NULL;
- }
- lidx = (ALsizei)VECTOR_SIZE(device->BufferList);
- VECTOR_PUSH_BACK(device->BufferList, empty_sublist);
- sublist = &VECTOR_BACK(device->BufferList);
- sublist->FreeMask = ~U64(0);
- sublist->Buffers = al_calloc(16, sizeof(ALbuffer)*64);
- if(UNLIKELY(!sublist->Buffers))
- {
- VECTOR_POP_BACK(device->BufferList);
- almtx_unlock(&device->BufferLock);
- alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate buffer batch");
- return NULL;
- }
-
- slidx = 0;
- buffer = sublist->Buffers + slidx;
- }
-
- memset(buffer, 0, sizeof(*buffer));
-
- /* Add 1 to avoid buffer ID 0. */
- buffer->id = ((lidx<<6) | slidx) + 1;
-
- sublist->FreeMask &= ~(U64(1)<<slidx);
- almtx_unlock(&device->BufferLock);
-
- return buffer;
-}
-
-static void FreeBuffer(ALCdevice *device, ALbuffer *buffer)
-{
- ALuint id = buffer->id - 1;
- ALsizei lidx = id >> 6;
- ALsizei slidx = id & 0x3f;
-
- al_free(buffer->data);
- memset(buffer, 0, sizeof(*buffer));
-
- VECTOR_ELEM(device->BufferList, lidx).FreeMask |= U64(1) << slidx;
-}
-
/*
* ReleaseALBuffers()
@@ -1301,5 +1198,5 @@ ALvoid ReleaseALBuffers(ALCdevice *device)
sublist->FreeMask = ~usemask;
}
if(leftover > 0)
- WARN("(%p) Deleted "SZFMT" Buffer%s\n", device, leftover, (leftover==1)?"":"s");
+ WARN("(%p) Deleted " SZFMT " Buffer%s\n", device, leftover, (leftover==1)?"":"s");
}
diff --git a/OpenAL32/alEffect.c b/OpenAL32/alEffect.c
index c2a78a0c..05a6c0a3 100644
--- a/OpenAL32/alEffect.c
+++ b/OpenAL32/alEffect.c
@@ -81,7 +81,7 @@ AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
context = GetContextRef();
if(!context) return;
- if(!(n >= 0))
+ if(n < 0)
alSetError(context, AL_INVALID_VALUE, "Generating %d effects", n);
else for(cur = 0;cur < n;cur++)
{
@@ -109,7 +109,7 @@ AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
device = context->Device;
LockEffectList(device);
- if(!(n >= 0))
+ if(n < 0)
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d effects", n);
for(i = 0;i < n;i++)
{
diff --git a/OpenAL32/alFilter.c b/OpenAL32/alFilter.c
index e57653e0..01da4008 100644
--- a/OpenAL32/alFilter.c
+++ b/OpenAL32/alFilter.c
@@ -61,7 +61,7 @@ AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
context = GetContextRef();
if(!context) return;
- if(!(n >= 0))
+ if(n < 0)
alSetError(context, AL_INVALID_VALUE, "Generating %d filters", n);
else for(cur = 0;cur < n;cur++)
{
@@ -90,7 +90,7 @@ AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
device = context->Device;
LockFilterList(device);
- if(!(n >= 0))
+ if(n < 0)
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d filters", n);
for(i = 0;i < n;i++)
{
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index d7c68e4e..1f76a069 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -988,7 +988,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid effect ID %u",
values[0]);
}
- if(!((ALuint)values[1] < (ALuint)device->NumAuxSends))
+ if((ALuint)values[1] >= (ALuint)device->NumAuxSends)
{
UnlockEffectSlotList(Context);
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid send %u", values[1]);
@@ -1683,7 +1683,7 @@ AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
context = GetContextRef();
if(!context) return;
- if(!(n >= 0))
+ if(n < 0)
alSetError(context, AL_INVALID_VALUE, "Generating %d sources", n);
else for(cur = 0;cur < n;cur++)
{
@@ -1710,7 +1710,7 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
if(!context) return;
LockSourceList(context);
- if(!(n >= 0))
+ if(n < 0)
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d sources", n);
/* Check that all Sources are valid */
@@ -1761,7 +1761,7 @@ AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
LockSourceList(Context);
if((Source=LookupSource(Context, source)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(FloatValsByProp(param) == 1))
+ else if(FloatValsByProp(param) != 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid float property 0x%04x", param);
else
SetSourcefv(Source, Context, param, &value);
@@ -1783,7 +1783,7 @@ AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1
LockSourceList(Context);
if((Source=LookupSource(Context, source)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(FloatValsByProp(param) == 3))
+ else if(FloatValsByProp(param) != 3)
alSetError(Context, AL_INVALID_ENUM, "Invalid 3-float property 0x%04x", param);
else
{
@@ -1810,7 +1810,7 @@ AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!values)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(FloatValsByProp(param) > 0))
+ else if(FloatValsByProp(param) < 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid float-vector property 0x%04x", param);
else
SetSourcefv(Source, Context, param, values);
@@ -1833,7 +1833,7 @@ AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble va
LockSourceList(Context);
if((Source=LookupSource(Context, source)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(DoubleValsByProp(param) == 1))
+ else if(DoubleValsByProp(param) != 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid double property 0x%04x", param);
else
{
@@ -1858,7 +1858,7 @@ AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble v
LockSourceList(Context);
if((Source=LookupSource(Context, source)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(DoubleValsByProp(param) == 3))
+ else if(DoubleValsByProp(param) != 3)
alSetError(Context, AL_INVALID_ENUM, "Invalid 3-double property 0x%04x", param);
else
{
@@ -1886,7 +1886,7 @@ AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdo
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!values)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!((count=DoubleValsByProp(param)) > 0 && count <= 6))
+ else if((count=DoubleValsByProp(param)) < 1 || count > 6)
alSetError(Context, AL_INVALID_ENUM, "Invalid double-vector property 0x%04x", param);
else
{
@@ -1916,7 +1916,7 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
LockSourceList(Context);
if((Source=LookupSource(Context, source)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(IntValsByProp(param) == 1))
+ else if(IntValsByProp(param) != 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid integer property 0x%04x", param);
else
SetSourceiv(Source, Context, param, &value);
@@ -1938,7 +1938,7 @@ AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, AL
LockSourceList(Context);
if((Source=LookupSource(Context, source)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(IntValsByProp(param) == 3))
+ else if(IntValsByProp(param) != 3)
alSetError(Context, AL_INVALID_ENUM, "Invalid 3-integer property 0x%04x", param);
else
{
@@ -1965,7 +1965,7 @@ AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *val
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!values)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(IntValsByProp(param) > 0))
+ else if(IntValsByProp(param) < 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid integer-vector property 0x%04x", param);
else
SetSourceiv(Source, Context, param, values);
@@ -1988,7 +1988,7 @@ AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SO
LockSourceList(Context);
if((Source=LookupSource(Context, source)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(Int64ValsByProp(param) == 1))
+ else if(Int64ValsByProp(param) != 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid integer64 property 0x%04x", param);
else
SetSourcei64v(Source, Context, param, &value);
@@ -2010,7 +2010,7 @@ AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOF
LockSourceList(Context);
if((Source=LookupSource(Context, source)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
- else if(!(Int64ValsByProp(param) == 3))
+ else if(Int64ValsByProp(param) != 3)
alSetError(Context, AL_INVALID_ENUM, "Invalid 3-integer64 property 0x%04x", param);
else
{
@@ -2037,7 +2037,7 @@ AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALin
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!values)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(Int64ValsByProp(param) > 0))
+ else if(Int64ValsByProp(param) < 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid integer64-vector property 0x%04x", param);
else
SetSourcei64v(Source, Context, param, values);
@@ -2061,7 +2061,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *val
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!value)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(FloatValsByProp(param) == 1))
+ else if(FloatValsByProp(param) != 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid float property 0x%04x", param);
else
{
@@ -2088,7 +2088,7 @@ AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *va
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!(value1 && value2 && value3))
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(FloatValsByProp(param) == 3))
+ else if(FloatValsByProp(param) != 3)
alSetError(Context, AL_INVALID_ENUM, "Invalid 3-float property 0x%04x", param);
else
{
@@ -2120,7 +2120,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *va
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!values)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!((count=FloatValsByProp(param)) > 0 && count <= 6))
+ else if((count=FloatValsByProp(param)) < 1 && count > 6)
alSetError(Context, AL_INVALID_ENUM, "Invalid float-vector property 0x%04x", param);
else
{
@@ -2151,7 +2151,7 @@ AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!value)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(DoubleValsByProp(param) == 1))
+ else if(DoubleValsByProp(param) != 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid double property 0x%04x", param);
else
GetSourcedv(Source, Context, param, value);
@@ -2173,7 +2173,7 @@ AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!(value1 && value2 && value3))
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(DoubleValsByProp(param) == 3))
+ else if(DoubleValsByProp(param) != 3)
alSetError(Context, AL_INVALID_ENUM, "Invalid 3-double property 0x%04x", param);
else
{
@@ -2203,7 +2203,7 @@ AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!values)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(DoubleValsByProp(param) > 0))
+ else if(DoubleValsByProp(param) < 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid double-vector property 0x%04x", param);
else
GetSourcedv(Source, Context, param, values);
@@ -2226,7 +2226,7 @@ AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!value)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(IntValsByProp(param) == 1))
+ else if(IntValsByProp(param) != 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid integer property 0x%04x", param);
else
GetSourceiv(Source, Context, param, value);
@@ -2249,7 +2249,7 @@ AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!(value1 && value2 && value3))
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(IntValsByProp(param) == 3))
+ else if(IntValsByProp(param) != 3)
alSetError(Context, AL_INVALID_ENUM, "Invalid 3-integer property 0x%04x", param);
else
{
@@ -2280,7 +2280,7 @@ AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!values)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(IntValsByProp(param) > 0))
+ else if(IntValsByProp(param) < 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid integer-vector property 0x%04x", param);
else
GetSourceiv(Source, Context, param, values);
@@ -2303,7 +2303,7 @@ AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64S
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!value)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(Int64ValsByProp(param) == 1))
+ else if(Int64ValsByProp(param) != 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid integer64 property 0x%04x", param);
else
GetSourcei64v(Source, Context, param, value);
@@ -2325,7 +2325,7 @@ AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!(value1 && value2 && value3))
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(Int64ValsByProp(param) == 3))
+ else if(Int64ValsByProp(param) != 3)
alSetError(Context, AL_INVALID_ENUM, "Invalid 3-integer64 property 0x%04x", param);
else
{
@@ -2355,7 +2355,7 @@ AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64
alSetError(Context, AL_INVALID_NAME, "Invalid source ID %u", source);
else if(!values)
alSetError(Context, AL_INVALID_VALUE, "NULL pointer");
- else if(!(Int64ValsByProp(param) > 0))
+ else if(Int64ValsByProp(param) < 1)
alSetError(Context, AL_INVALID_ENUM, "Invalid integer64-vector property 0x%04x", param);
else
GetSourcei64v(Source, Context, param, values);
@@ -2568,7 +2568,7 @@ AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
if(!context) return;
LockSourceList(context);
- if(!(n >= 0))
+ if(n < 0)
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Pausing %d sources", n);
for(i = 0;i < n;i++)
{
@@ -2612,7 +2612,7 @@ AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
if(!context) return;
LockSourceList(context);
- if(!(n >= 0))
+ if(n < 0)
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Stopping %d sources", n);
for(i = 0;i < n;i++)
{
@@ -2664,7 +2664,7 @@ AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
if(!context) return;
LockSourceList(context);
- if(!(n >= 0))
+ if(n < 0)
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Rewinding %d sources", n);
for(i = 0;i < n;i++)
{
diff --git a/appveyor.yml b/appveyor.yml
index 6d826eed..010a2da1 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 1.19.0.{build}
+version: 1.19.1.{build}
environment:
matrix:
@@ -14,6 +14,6 @@ install:
build_script:
- cd build
- - cmake -G"%GEN%" -DALSOFT_REQUIRE_WINMM=ON -DALSOFT_REQUIRE_DSOUND=ON -DALSOFT_REQUIRE_WASAPI=ON -DALSOFT_EMBED_HRTF_DATA=YES ..
+ - cmake -G"%GEN%" -DALSOFT_BUILD_ROUTER=ON -DALSOFT_REQUIRE_WINMM=ON -DALSOFT_REQUIRE_DSOUND=ON -DALSOFT_REQUIRE_WASAPI=ON -DALSOFT_EMBED_HRTF_DATA=YES ..
- cmake --build . --config %CFG% --clean-first
diff --git a/common/align.h b/common/align.h
index e2dc81df..53a5806a 100644
--- a/common/align.h
+++ b/common/align.h
@@ -5,11 +5,8 @@
#include <stdalign.h>
#endif
-#ifndef alignas
-#if defined(IN_IDE_PARSER)
-/* KDevelop has problems with our align macro, so just use nothing for parsing. */
-#define alignas(x)
-#elif defined(HAVE_C11_ALIGNAS)
+#if !defined(alignas) && !defined(__cplusplus)
+#if defined(HAVE_C11_ALIGNAS)
#define alignas _Alignas
#else
/* NOTE: Our custom ALIGN macro can't take a type name like alignas can. For
diff --git a/common/atomic.h b/common/atomic.h
index 39daa1dc..17e616bb 100644
--- a/common/atomic.h
+++ b/common/atomic.h
@@ -17,6 +17,52 @@
#define CONST_CAST(T, V) ((T)(V))
#endif
+#ifdef HAVE_C11_ATOMIC
+#ifdef __cplusplus
+/* C++11 doesn't support compatibility with C11 atomics. So instead, make C++11
+ * atomic declarations global to emulate C11. There's no standard guarantee of
+ * ABI compatibility, but it's desired behavior that mostly works. See:
+ *
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0943r1.html
+ *
+ * Any alignment issues arising from this can be fixed with explicit alignas()
+ * specifiers on affected variables.
+ *
+ * Only do this when C11 atomics are supported in C, since MSVC and pre-C11
+ * compilers may use something else that is significantly different in C
+ * despite supporting C++11 atomics.
+ */
+#include <atomic>
+
+#define _Atomic(T) std::atomic<T>
+using std::memory_order;
+using std::memory_order_relaxed;
+using std::memory_order_consume;
+using std::memory_order_acquire;
+using std::memory_order_release;
+using std::memory_order_acq_rel;
+using std::memory_order_seq_cst;
+
+using std::atomic_flag;
+
+using std::atomic_init;
+using std::atomic_load_explicit;
+using std::atomic_store_explicit;
+using std::atomic_fetch_add_explicit;
+using std::atomic_fetch_sub_explicit;
+using std::atomic_exchange_explicit;
+using std::atomic_compare_exchange_strong_explicit;
+using std::atomic_compare_exchange_weak_explicit;
+using std::atomic_flag_test_and_set_explicit;
+using std::atomic_flag_clear_explicit;
+using std::atomic_thread_fence;
+
+#else
+
+#include <stdatomic.h>
+#endif /* __cplusplus */
+#endif /* HAVE_C11_ATOMIC */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -24,8 +70,6 @@ extern "C" {
/* Atomics using C11 */
#ifdef HAVE_C11_ATOMIC
-#include <stdatomic.h>
-
#define almemory_order memory_order
#define almemory_order_relaxed memory_order_relaxed
#define almemory_order_consume memory_order_consume
@@ -34,7 +78,7 @@ extern "C" {
#define almemory_order_acq_rel memory_order_acq_rel
#define almemory_order_seq_cst memory_order_seq_cst
-#define ATOMIC(T) T _Atomic
+#define ATOMIC(T) _Atomic(T)
#define ATOMIC_FLAG atomic_flag
#define ATOMIC_INIT atomic_init
@@ -119,26 +163,26 @@ enum almemory_order {
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
#define WRAP_ADD(S, ret, dest, incr) __asm__ __volatile__( \
- "lock; xadd"S" %0,(%1)" \
+ "lock; xadd" S " %0,(%1)" \
: "=r" (ret) \
: "r" (dest), "0" (incr) \
: "memory" \
)
#define WRAP_SUB(S, ret, dest, decr) __asm__ __volatile__( \
- "lock; xadd"S" %0,(%1)" \
+ "lock; xadd" S " %0,(%1)" \
: "=r" (ret) \
: "r" (dest), "0" (-(decr)) \
: "memory" \
)
#define WRAP_XCHG(S, ret, dest, newval) __asm__ __volatile__( \
- "lock; xchg"S" %0,(%1)" \
+ "lock; xchg" S " %0,(%1)" \
: "=r" (ret) \
: "r" (dest), "0" (newval) \
: "memory" \
)
#define WRAP_CMPXCHG(S, ret, dest, oldval, newval) __asm__ __volatile__( \
- "lock; cmpxchg"S" %2,(%1)" \
+ "lock; cmpxchg" S " %2,(%1)" \
: "=a" (ret) \
: "r" (dest), "r" (newval), "0" (oldval) \
: "memory" \
@@ -415,9 +459,9 @@ inline void InitRef(RefCount *ptr, uint value)
inline uint ReadRef(RefCount *ptr)
{ return ATOMIC_LOAD(ptr, almemory_order_acquire); }
inline uint IncrementRef(RefCount *ptr)
-{ return ATOMIC_ADD(ptr, 1, almemory_order_acq_rel)+1; }
+{ return ATOMIC_ADD(ptr, 1u, almemory_order_acq_rel)+1; }
inline uint DecrementRef(RefCount *ptr)
-{ return ATOMIC_SUB(ptr, 1, almemory_order_acq_rel)-1; }
+{ return ATOMIC_SUB(ptr, 1u, almemory_order_acq_rel)-1; }
/* WARNING: A livelock is theoretically possible if another thread keeps
diff --git a/common/bool.h b/common/bool.h
index 6f714d09..eb1d9174 100644
--- a/common/bool.h
+++ b/common/bool.h
@@ -5,7 +5,7 @@
#include <stdbool.h>
#endif
-#ifndef bool
+#if !defined(bool) && !defined(__cplusplus)
#ifdef HAVE_C99_BOOL
#define bool _Bool
#else
diff --git a/common/math_defs.h b/common/math_defs.h
index aa79b695..1b24bec4 100644
--- a/common/math_defs.h
+++ b/common/math_defs.h
@@ -33,21 +33,23 @@ static const union msvc_inf_hack {
#endif
#ifndef HAVE_LOG2F
-static inline float log2f(float f)
+static inline float my_log2f(float f)
{
return logf(f) / logf(2.0f);
}
+#define log2f my_log2f
#endif
#ifndef HAVE_CBRTF
-static inline float cbrtf(float f)
+static inline float my_cbrtf(float f)
{
return powf(f, 1.0f/3.0f);
}
+#define cbrtf my_cbrtf
#endif
#ifndef HAVE_COPYSIGNF
-static inline float copysignf(float x, float y)
+static inline float my_copysignf(float x, float y)
{
union {
float f;
@@ -57,6 +59,7 @@ static inline float copysignf(float x, float y)
ux.u |= (uy.u&0x80000000u);
return ux.f;
}
+#define copysignf my_copysignf
#endif
#define DEG2RAD(x) ((float)(x) * (float)(M_PI/180.0))
diff --git a/common/static_assert.h b/common/static_assert.h
index bf0ce065..3a554fb5 100644
--- a/common/static_assert.h
+++ b/common/static_assert.h
@@ -4,7 +4,7 @@
#include <assert.h>
-#ifndef static_assert
+#if !defined(static_assert) && !defined(__cplusplus)
#ifdef HAVE_C11_STATIC_ASSERT
#define static_assert _Static_assert
#else
diff --git a/common/threads.c b/common/threads.c
index 6cfe383b..e8301297 100644
--- a/common/threads.c
+++ b/common/threads.c
@@ -631,6 +631,39 @@ void alcnd_destroy(alcnd_t *cond)
}
+#ifdef __APPLE__
+
+int alsem_init(alsem_t *sem, unsigned int initial)
+{
+ *sem = dispatch_semaphore_create(initial);
+ return *sem ? althrd_success : althrd_error;
+}
+
+void alsem_destroy(alsem_t *sem)
+{
+ dispatch_release(*sem);
+}
+
+int alsem_post(alsem_t *sem)
+{
+ dispatch_semaphore_signal(*sem);
+ return althrd_success;
+}
+
+int alsem_wait(alsem_t *sem)
+{
+ dispatch_semaphore_wait(*sem, DISPATCH_TIME_FOREVER);
+ return althrd_success;
+}
+
+int alsem_trywait(alsem_t *sem)
+{
+ long value = dispatch_semaphore_wait(*sem, DISPATCH_TIME_NOW);
+ return value == 0 ? althrd_success : althrd_busy;
+}
+
+#else /* !__APPLE__ */
+
int alsem_init(alsem_t *sem, unsigned int initial)
{
if(sem_init(sem, 0, initial) == 0)
@@ -665,6 +698,8 @@ int alsem_trywait(alsem_t *sem)
return althrd_error;
}
+#endif /* __APPLE__ */
+
int altss_create(altss_t *tss_id, altss_dtor_t callback)
{
diff --git a/common/threads.h b/common/threads.h
index b0bebd8d..7fbe20cd 100644
--- a/common/threads.h
+++ b/common/threads.h
@@ -130,13 +130,21 @@ inline int altss_set(altss_t tss_id, void *val)
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
+#ifdef __APPLE__
+#include <dispatch/dispatch.h>
+#else /* !__APPLE__ */
#include <semaphore.h>
+#endif /* __APPLE__ */
typedef pthread_t althrd_t;
typedef pthread_mutex_t almtx_t;
typedef pthread_cond_t alcnd_t;
+#ifdef __APPLE__
+typedef dispatch_semaphore_t alsem_t;
+#else /* !__APPLE__ */
typedef sem_t alsem_t;
+#endif /* __APPLE__ */
typedef pthread_key_t altss_t;
typedef pthread_once_t alonce_flag;
@@ -254,7 +262,66 @@ int altimespec_get(struct timespec *ts, int base);
void al_nssleep(unsigned long nsec);
#ifdef __cplusplus
-}
+} // extern "C"
+
+#include <mutex>
+
+/* Add specializations for std::lock_guard and std::unique_lock which take an
+ * almtx_t and call the appropriate almtx_* functions.
+ */
+namespace std {
+
+template<>
+class lock_guard<almtx_t> {
+ almtx_t &mMtx;
+
+public:
+ using mutex_type = almtx_t;
+
+ explicit lock_guard(almtx_t &mtx) : mMtx(mtx) { almtx_lock(&mMtx); }
+ lock_guard(almtx_t &mtx, std::adopt_lock_t) : mMtx(mtx) { }
+ ~lock_guard() { almtx_unlock(&mMtx); }
+
+ lock_guard(const lock_guard&) = delete;
+ lock_guard& operator=(const lock_guard&) = delete;
+};
+
+template<>
+class unique_lock<almtx_t> {
+ almtx_t *mMtx{nullptr};
+ bool mLocked{false};
+
+public:
+ using mutex_type = almtx_t;
+
+ explicit unique_lock(almtx_t &mtx) : mMtx(&mtx) { almtx_lock(mMtx); mLocked = true; }
+ unique_lock(unique_lock&& rhs) : mMtx(rhs.mMtx), mLocked(rhs.mLocked)
+ { rhs.mMtx = nullptr; rhs.mLocked = false; }
+ ~unique_lock() { if(mLocked) almtx_unlock(mMtx); }
+
+ unique_lock& operator=(const unique_lock&) = delete;
+ unique_lock& operator=(unique_lock&& rhs)
+ {
+ if(mLocked)
+ almtx_unlock(mMtx);
+ mMtx = rhs.mMtx; rhs.mMtx = nullptr;
+ mLocked = rhs.mLocked; rhs.mLocked = false;
+ return *this;
+ }
+
+ void lock()
+ {
+ almtx_lock(mMtx);
+ mLocked = true;
+ }
+ void unlock()
+ {
+ mLocked = false;
+ almtx_unlock(mMtx);
+ }
+};
+
+} // namespace std
#endif
#endif /* AL_THREADS_H */
diff --git a/common/uintmap.c b/common/uintmap.c
index 18d52d64..3654779c 100644
--- a/common/uintmap.c
+++ b/common/uintmap.c
@@ -47,7 +47,7 @@ ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
do {
ALsizei step = count>>1;
ALsizei i = pos+step;
- if(!(map->keys[i] < key))
+ if(map->keys[i] >= key)
count = step;
else
{
@@ -130,7 +130,7 @@ ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
do {
ALsizei step = count>>1;
ALsizei i = pos+step;
- if(!(map->keys[i] < key))
+ if(map->keys[i] >= key)
count = step;
else
{
@@ -166,7 +166,7 @@ ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
do {
ALsizei step = count>>1;
ALsizei i = pos+step;
- if(!(map->keys[i] < key))
+ if(map->keys[i] >= key)
count = step;
else
{
diff --git a/config.h.in b/config.h.in
index 9cc6c16b..5b4bdfde 100644
--- a/config.h.in
+++ b/config.h.in
@@ -8,6 +8,9 @@
/* Define a built-in call indicating an aligned data pointer */
#define ASSUME_ALIGNED(x, y) ${ASSUME_ALIGNED_DECL}
+/* Define a restrict macro for non-aliased pointers */
+#define RESTRICT ${RESTRICT_DECL}
+
/* Define if HRTF data is embedded in the library */
#cmakedefine ALSOFT_EMBED_HRTF_DATA
diff --git a/examples/alrecord.c b/examples/alrecord.c
index 43b26d35..f60a3055 100644
--- a/examples/alrecord.c
+++ b/examples/alrecord.c
@@ -133,7 +133,7 @@ int main(int argc, char **argv)
break;
else if(strcmp(argv[0], "--channels") == 0 || strcmp(argv[0], "-c") == 0)
{
- if(!(argc > 1))
+ if(argc < 2)
{
fprintf(stderr, "Missing argument for option: %s\n", argv[0]);
return 1;
@@ -150,7 +150,7 @@ int main(int argc, char **argv)
}
else if(strcmp(argv[0], "--bits") == 0 || strcmp(argv[0], "-b") == 0)
{
- if(!(argc > 1))
+ if(argc < 2)
{
fprintf(stderr, "Missing argument for option: %s\n", argv[0]);
return 1;
@@ -168,7 +168,7 @@ int main(int argc, char **argv)
}
else if(strcmp(argv[0], "--rate") == 0 || strcmp(argv[0], "-r") == 0)
{
- if(!(argc > 1))
+ if(argc < 2)
{
fprintf(stderr, "Missing argument for option: %s\n", argv[0]);
return 1;
@@ -185,7 +185,7 @@ int main(int argc, char **argv)
}
else if(strcmp(argv[0], "--time") == 0 || strcmp(argv[0], "-t") == 0)
{
- if(!(argc > 1))
+ if(argc < 2)
{
fprintf(stderr, "Missing argument for option: %s\n", argv[0]);
return 1;
@@ -202,7 +202,7 @@ int main(int argc, char **argv)
}
else if(strcmp(argv[0], "--outfile") == 0 || strcmp(argv[0], "-o") == 0)
{
- if(!(argc > 1))
+ if(argc < 2)
{
fprintf(stderr, "Missing argument for option: %s\n", argv[0]);
return 1;
diff --git a/router/al.c b/router/al.cpp
index 8dd888d9..4c8b0006 100644
--- a/router/al.c
+++ b/router/al.cpp
@@ -7,36 +7,36 @@
#include "router.h"
-atomic_DriverIfacePtr CurrentCtxDriver = ATOMIC_INIT_STATIC(NULL);
+std::atomic<DriverIface*> CurrentCtxDriver{nullptr};
#define DECL_THUNK1(R,n,T1) AL_API R AL_APIENTRY n(T1 a) \
{ \
- DriverIface *iface = altss_get(ThreadCtxDriver); \
- if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
+ DriverIface *iface = ThreadCtxDriver; \
+ if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
return iface->n(a); \
}
#define DECL_THUNK2(R,n,T1,T2) AL_API R AL_APIENTRY n(T1 a, T2 b) \
{ \
- DriverIface *iface = altss_get(ThreadCtxDriver); \
- if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
+ DriverIface *iface = ThreadCtxDriver; \
+ if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
return iface->n(a, b); \
}
#define DECL_THUNK3(R,n,T1,T2,T3) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c) \
{ \
- DriverIface *iface = altss_get(ThreadCtxDriver); \
- if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
+ DriverIface *iface = ThreadCtxDriver; \
+ if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
return iface->n(a, b, c); \
}
#define DECL_THUNK4(R,n,T1,T2,T3,T4) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c, T4 d) \
{ \
- DriverIface *iface = altss_get(ThreadCtxDriver); \
- if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
+ DriverIface *iface = ThreadCtxDriver; \
+ if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
return iface->n(a, b, c, d); \
}
#define DECL_THUNK5(R,n,T1,T2,T3,T4,T5) AL_API R AL_APIENTRY n(T1 a, T2 b, T3 c, T4 d, T5 e) \
{ \
- DriverIface *iface = altss_get(ThreadCtxDriver); \
- if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);\
+ DriverIface *iface = ThreadCtxDriver; \
+ if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire); \
return iface->n(a, b, c, d, e); \
}
@@ -46,8 +46,8 @@ atomic_DriverIfacePtr CurrentCtxDriver = ATOMIC_INIT_STATIC(NULL);
*/
AL_API ALenum AL_APIENTRY alGetError(void)
{
- DriverIface *iface = altss_get(ThreadCtxDriver);
- if(!iface) iface = ATOMIC_LOAD(&CurrentCtxDriver, almemory_order_acquire);
+ DriverIface *iface = ThreadCtxDriver;
+ if(!iface) iface = CurrentCtxDriver.load(std::memory_order_acquire);
return iface ? iface->alGetError() : AL_NO_ERROR;
}
diff --git a/router/alc.c b/router/alc.cpp
index 946c7d4c..c129198a 100644
--- a/router/alc.c
+++ b/router/alc.cpp
@@ -6,18 +6,20 @@
#include <string.h>
#include <stdio.h>
+#include <mutex>
+#include <algorithm>
+#include <array>
+
#include "AL/alc.h"
#include "router.h"
-#include "almalloc.h"
-
-#define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
-#define DECL(x) { #x, (ALCvoid*)(x) }
-static const struct {
+#define DECL(x) { #x, reinterpret_cast<void*>(x) }
+struct FuncExportEntry {
const ALCchar *funcName;
ALCvoid *address;
-} alcFunctions[] = {
+};
+static const std::array<FuncExportEntry,95> alcFunctions{{
DECL(alcCreateContext),
DECL(alcMakeContextCurrent),
DECL(alcProcessContext),
@@ -115,14 +117,15 @@ static const struct {
DECL(alDopplerVelocity),
DECL(alSpeedOfSound),
DECL(alDistanceModel),
-};
+}};
#undef DECL
#define DECL(x) { #x, (x) }
-static const struct {
+struct EnumExportEntry {
const ALCchar *enumName;
ALCenum value;
-} alcEnumerations[] = {
+};
+static const std::array<EnumExportEntry,92> alcEnumerations{{
DECL(ALC_INVALID),
DECL(ALC_FALSE),
DECL(ALC_TRUE),
@@ -228,7 +231,7 @@ static const struct {
DECL(AL_LINEAR_DISTANCE_CLAMPED),
DECL(AL_EXPONENT_DISTANCE),
DECL(AL_EXPONENT_DISTANCE_CLAMPED),
-};
+}};
#undef DECL
static const ALCchar alcNoError[] = "No Error";
@@ -245,77 +248,54 @@ static const ALCint alcMajorVersion = 1;
static const ALCint alcMinorVersion = 1;
-static almtx_t EnumerationLock;
-static almtx_t ContextSwitchLock;
+static std::mutex EnumerationLock;
+static std::mutex ContextSwitchLock;
-static ATOMIC(ALCenum) LastError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
-static PtrIntMap DeviceIfaceMap = PTRINTMAP_STATIC_INITIALIZE;
-static PtrIntMap ContextIfaceMap = PTRINTMAP_STATIC_INITIALIZE;
+static std::atomic<ALCenum> LastError{ALC_NO_ERROR};
+static PtrIntMap DeviceIfaceMap;
+static PtrIntMap ContextIfaceMap;
typedef struct EnumeratedList {
- ALCchar *Names;
- ALCchar *NamesEnd;
- ALCint *Indicies;
- ALCsizei IndexSize;
-} EnumeratedList;
-static EnumeratedList DevicesList = { NULL, NULL, NULL, 0 };
-static EnumeratedList AllDevicesList = { NULL, NULL, NULL, 0 };
-static EnumeratedList CaptureDevicesList = { NULL, NULL, NULL, 0 };
-
-static void ClearDeviceList(EnumeratedList *list)
-{
- al_free(list->Names);
- list->Names = NULL;
- list->NamesEnd = NULL;
+ std::vector<ALCchar> Names;
+ std::vector<ALCint> Indicies;
- al_free(list->Indicies);
- list->Indicies = NULL;
- list->IndexSize = 0;
-}
+ void clear()
+ {
+ Names.clear();
+ Indicies.clear();
+ }
+} EnumeratedList;
+static EnumeratedList DevicesList;
+static EnumeratedList AllDevicesList;
+static EnumeratedList CaptureDevicesList;
static void AppendDeviceList(EnumeratedList *list, const ALCchar *names, ALint idx)
{
const ALCchar *name_end = names;
- ALCsizei count = 0;
- ALCchar *new_list;
- ALCint *new_indicies;
- size_t len;
- ALCsizei i;
+ if(!name_end) return;
- if(!name_end)
- return;
+ ALCsizei count = 0;
while(*name_end)
{
TRACE("Enumerated \"%s\", driver %d\n", name_end, idx);
- count++;
+ ++count;
name_end += strlen(name_end)+1;
}
if(names == name_end)
return;
- len = (list->NamesEnd - list->Names) + (name_end - names);
- new_list = al_calloc(DEF_ALIGN, len + 1);
- memcpy(new_list, list->Names, list->NamesEnd - list->Names);
- memcpy(new_list + (list->NamesEnd - list->Names), names, name_end - names);
- al_free(list->Names);
- list->Names = new_list;
- list->NamesEnd = list->Names + len;
-
- new_indicies = al_calloc(16, sizeof(ALCint)*(list->IndexSize + count));
- for(i = 0;i < list->IndexSize;i++)
- new_indicies[i] = list->Indicies[i];
- for(i = 0;i < count;i++)
- new_indicies[list->IndexSize+i] = idx;
- al_free(list->Indicies);
- list->Indicies = new_indicies;
- list->IndexSize += count;
+ list->Names.reserve(list->Names.size() + (name_end - names) + 1);
+ list->Names.insert(list->Names.cend(), names, name_end);
+
+ list->Indicies.reserve(list->Indicies.size() + count);
+ list->Indicies.insert(list->Indicies.cend(), count, idx);
}
static ALint GetDriverIndexForName(const EnumeratedList *list, const ALCchar *name)
{
- const ALCchar *devnames = list->Names;
- const ALCint *index = list->Indicies;
+ const ALCchar *devnames = list->Names.data();
+ const ALCint *index = list->Indicies.data();
while(devnames && *devnames)
{
@@ -327,30 +307,11 @@ static ALint GetDriverIndexForName(const EnumeratedList *list, const ALCchar *na
return -1;
}
-void InitALC(void)
-{
- almtx_init(&EnumerationLock, almtx_recursive);
- almtx_init(&ContextSwitchLock, almtx_plain);
-}
-
-void ReleaseALC(void)
-{
- ClearDeviceList(&DevicesList);
- ClearDeviceList(&AllDevicesList);
- ClearDeviceList(&CaptureDevicesList);
-
- ResetPtrIntMap(&ContextIfaceMap);
- ResetPtrIntMap(&DeviceIfaceMap);
-
- almtx_destroy(&ContextSwitchLock);
- almtx_destroy(&EnumerationLock);
-}
-
ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename)
{
- ALCdevice *device = NULL;
- ALint idx;
+ ALCdevice *device = nullptr;
+ ALint idx = 0;
/* Prior to the enumeration extension, apps would hardcode these names as a
* quality hint for the wrapper driver. Ignore them since there's no sane
@@ -360,51 +321,51 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename)
strcmp(devicename, "DirectSound3D") == 0 ||
strcmp(devicename, "DirectSound") == 0 ||
strcmp(devicename, "MMSYSTEM") == 0))
- devicename = NULL;
+ devicename = nullptr;
if(devicename)
{
- almtx_lock(&EnumerationLock);
- if(!DevicesList.Names)
- (void)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
- idx = GetDriverIndexForName(&DevicesList, devicename);
- if(idx < 0)
- {
- if(!AllDevicesList.Names)
- (void)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
- idx = GetDriverIndexForName(&AllDevicesList, devicename);
+ { std::lock_guard<std::mutex> _{EnumerationLock};
+ if(DevicesList.Names.empty())
+ (void)alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
+ idx = GetDriverIndexForName(&DevicesList, devicename);
+ if(idx < 0)
+ {
+ if(AllDevicesList.Names.empty())
+ (void)alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
+ idx = GetDriverIndexForName(&AllDevicesList, devicename);
+ }
}
- almtx_unlock(&EnumerationLock);
+
if(idx < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_VALUE);
+ LastError.store(ALC_INVALID_VALUE);
TRACE("Failed to find driver for name \"%s\"\n", devicename);
- return NULL;
+ return nullptr;
}
TRACE("Found driver %d for name \"%s\"\n", idx, devicename);
device = DriverList[idx].alcOpenDevice(devicename);
}
else
{
- int i;
- for(i = 0;i < DriverListSize;i++)
+ for(const auto &drv : DriverList)
{
- if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
- DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
+ if(drv.ALCVer >= MAKE_ALC_VER(1, 1) ||
+ drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
{
- idx = i;
TRACE("Using default device from driver %d\n", idx);
- device = DriverList[idx].alcOpenDevice(NULL);
+ device = drv.alcOpenDevice(nullptr);
break;
}
+ ++idx;
}
}
if(device)
{
- if(InsertPtrIntMapEntry(&DeviceIfaceMap, device, idx) != ALC_NO_ERROR)
+ if(DeviceIfaceMap.insert(device, idx) != ALC_NO_ERROR)
{
DriverList[idx].alcCloseDevice(device);
- device = NULL;
+ device = nullptr;
}
}
@@ -415,14 +376,14 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
{
ALint idx;
- if(!device || (idx=LookupPtrIntMapKey(&DeviceIfaceMap, device)) < 0)
+ if(!device || (idx=DeviceIfaceMap.lookupByKey(device)) < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
return ALC_FALSE;
}
if(!DriverList[idx].alcCloseDevice(device))
return ALC_FALSE;
- RemovePtrIntMapKey(&DeviceIfaceMap, device);
+ DeviceIfaceMap.removeByKey(device);
return ALC_TRUE;
}
@@ -432,18 +393,18 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
ALCcontext *context;
ALint idx;
- if(!device || (idx=LookupPtrIntMapKey(&DeviceIfaceMap, device)) < 0)
+ if(!device || (idx=DeviceIfaceMap.lookupByKey(device)) < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
- return ALC_FALSE;
+ LastError.store(ALC_INVALID_DEVICE);
+ return nullptr;
}
context = DriverList[idx].alcCreateContext(device, attrlist);
if(context)
{
- if(InsertPtrIntMapEntry(&ContextIfaceMap, context, idx) != ALC_NO_ERROR)
+ if(ContextIfaceMap.insert(context, idx) != ALC_NO_ERROR)
{
DriverList[idx].alcDestroyContext(context);
- context = NULL;
+ context = nullptr;
}
}
@@ -454,21 +415,17 @@ ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
{
ALint idx = -1;
- almtx_lock(&ContextSwitchLock);
+ std::lock_guard<std::mutex> _{ContextSwitchLock};
if(context)
{
- idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
+ idx = ContextIfaceMap.lookupByKey(context);
if(idx < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
- almtx_unlock(&ContextSwitchLock);
+ LastError.store(ALC_INVALID_CONTEXT);
return ALC_FALSE;
}
if(!DriverList[idx].alcMakeContextCurrent(context))
- {
- almtx_unlock(&ContextSwitchLock);
return ALC_FALSE;
- }
}
/* Unset the context from the old driver if it's different from the new
@@ -476,22 +433,21 @@ ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
*/
if(idx < 0)
{
- DriverIface *oldiface = altss_get(ThreadCtxDriver);
- if(oldiface) oldiface->alcSetThreadContext(NULL);
- oldiface = ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver, NULL);
- if(oldiface) oldiface->alcMakeContextCurrent(NULL);
+ DriverIface *oldiface = ThreadCtxDriver;
+ if(oldiface) oldiface->alcSetThreadContext(nullptr);
+ oldiface = CurrentCtxDriver.exchange(nullptr);
+ if(oldiface) oldiface->alcMakeContextCurrent(nullptr);
}
else
{
- DriverIface *oldiface = altss_get(ThreadCtxDriver);
+ DriverIface *oldiface = ThreadCtxDriver;
if(oldiface && oldiface != &DriverList[idx])
- oldiface->alcSetThreadContext(NULL);
- oldiface = ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver, &DriverList[idx]);
+ oldiface->alcSetThreadContext(nullptr);
+ oldiface = CurrentCtxDriver.exchange(&DriverList[idx]);
if(oldiface && oldiface != &DriverList[idx])
- oldiface->alcMakeContextCurrent(NULL);
+ oldiface->alcMakeContextCurrent(nullptr);
}
- almtx_unlock(&ContextSwitchLock);
- altss_set(ThreadCtxDriver, NULL);
+ ThreadCtxDriver = nullptr;
return ALC_TRUE;
}
@@ -500,55 +456,55 @@ ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
{
if(context)
{
- ALint idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
+ ALint idx = ContextIfaceMap.lookupByKey(context);
if(idx >= 0)
return DriverList[idx].alcProcessContext(context);
}
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
+ LastError.store(ALC_INVALID_CONTEXT);
}
ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
{
if(context)
{
- ALint idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
+ ALint idx = ContextIfaceMap.lookupByKey(context);
if(idx >= 0)
return DriverList[idx].alcSuspendContext(context);
}
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
+ LastError.store(ALC_INVALID_CONTEXT);
}
ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
{
ALint idx;
- if(!context || (idx=LookupPtrIntMapKey(&ContextIfaceMap, context)) < 0)
+ if(!context || (idx=ContextIfaceMap.lookupByKey(context)) < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
+ LastError.store(ALC_INVALID_CONTEXT);
return;
}
DriverList[idx].alcDestroyContext(context);
- RemovePtrIntMapKey(&ContextIfaceMap, context);
+ ContextIfaceMap.removeByKey(context);
}
ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
{
- DriverIface *iface = altss_get(ThreadCtxDriver);
- if(!iface) iface = ATOMIC_LOAD_SEQ(&CurrentCtxDriver);
- return iface ? iface->alcGetCurrentContext() : NULL;
+ DriverIface *iface = ThreadCtxDriver;
+ if(!iface) iface = CurrentCtxDriver.load();
+ return iface ? iface->alcGetCurrentContext() : nullptr;
}
ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context)
{
if(context)
{
- ALint idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
+ ALint idx = ContextIfaceMap.lookupByKey(context);
if(idx >= 0)
return DriverList[idx].alcGetContextsDevice(context);
}
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
- return NULL;
+ LastError.store(ALC_INVALID_CONTEXT);
+ return nullptr;
}
@@ -556,11 +512,11 @@ ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
{
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx < 0) return ALC_INVALID_DEVICE;
return DriverList[idx].alcGetError(device);
}
- return ATOMIC_EXCHANGE_SEQ(&LastError, ALC_NO_ERROR);
+ return LastError.exchange(ALC_NO_ERROR);
}
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname)
@@ -570,10 +526,10 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
return ALC_FALSE;
}
return DriverList[idx].alcIsExtensionPresent(device, extname);
@@ -585,7 +541,7 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A
{
if(strncasecmp(ptr, extname, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
return ALC_TRUE;
- if((ptr=strchr(ptr, ' ')) != NULL)
+ if((ptr=strchr(ptr, ' ')) != nullptr)
{
do {
++ptr;
@@ -597,61 +553,53 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A
ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname)
{
- size_t i;
-
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
- return NULL;
+ LastError.store(ALC_INVALID_DEVICE);
+ return nullptr;
}
return DriverList[idx].alcGetProcAddress(device, funcname);
}
- for(i = 0;i < COUNTOF(alcFunctions);i++)
- {
- if(strcmp(funcname, alcFunctions[i].funcName) == 0)
- return alcFunctions[i].address;
- }
- return NULL;
+ auto entry = std::find_if(alcFunctions.cbegin(), alcFunctions.cend(),
+ [funcname](const FuncExportEntry &entry) -> bool
+ { return strcmp(funcname, entry.funcName) == 0; }
+ );
+ return (entry != alcFunctions.cend()) ? entry->address : nullptr;
}
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname)
{
- size_t i;
-
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
return 0;
}
return DriverList[idx].alcGetEnumValue(device, enumname);
}
- for(i = 0;i < COUNTOF(alcEnumerations);i++)
- {
- if(strcmp(enumname, alcEnumerations[i].enumName) == 0)
- return alcEnumerations[i].value;
- }
- return 0;
+ auto entry = std::find_if(alcEnumerations.cbegin(), alcEnumerations.cend(),
+ [enumname](const EnumExportEntry &entry) -> bool
+ { return strcmp(enumname, entry.enumName) == 0; }
+ );
+ return (entry != alcEnumerations.cend()) ? entry->value : 0;
}
ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param)
{
- ALsizei i = 0;
-
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
- return NULL;
+ LastError.store(ALC_INVALID_DEVICE);
+ return nullptr;
}
return DriverList[idx].alcGetString(device, param);
}
@@ -674,104 +622,135 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum para
return alcExtensionList;
case ALC_DEVICE_SPECIFIER:
- almtx_lock(&EnumerationLock);
- ClearDeviceList(&DevicesList);
- for(i = 0;i < DriverListSize;i++)
+ { std::lock_guard<std::mutex> _{EnumerationLock};
+ DevicesList.clear();
+ ALint idx = 0;
+ for(const auto &drv : DriverList)
{
/* Only enumerate names from drivers that support it. */
- if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
- DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
+ if(drv.ALCVer >= MAKE_ALC_VER(1, 1) ||
+ drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
AppendDeviceList(&DevicesList,
- DriverList[i].alcGetString(NULL, ALC_DEVICE_SPECIFIER), i
+ drv.alcGetString(nullptr, ALC_DEVICE_SPECIFIER), idx
);
+ idx++;
}
- almtx_unlock(&EnumerationLock);
- return DevicesList.Names;
+ /* Ensure the list is double-null termianted. */
+ if(DevicesList.Names.empty())
+ DevicesList.Names.emplace_back(0);
+ DevicesList.Names.emplace_back(0);
+ return DevicesList.Names.data();
+ }
case ALC_ALL_DEVICES_SPECIFIER:
- almtx_lock(&EnumerationLock);
- ClearDeviceList(&AllDevicesList);
- for(i = 0;i < DriverListSize;i++)
+ { std::lock_guard<std::mutex> _{EnumerationLock};
+ AllDevicesList.clear();
+ ALint idx = 0;
+ for(const auto &drv : DriverList)
{
/* If the driver doesn't support ALC_ENUMERATE_ALL_EXT, substitute
* standard enumeration.
*/
- if(DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
+ if(drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"))
AppendDeviceList(&AllDevicesList,
- DriverList[i].alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER), i
+ drv.alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER), idx
);
- else if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
- DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
+ else if(drv.ALCVer >= MAKE_ALC_VER(1, 1) ||
+ drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
AppendDeviceList(&AllDevicesList,
- DriverList[i].alcGetString(NULL, ALC_DEVICE_SPECIFIER), i
+ drv.alcGetString(nullptr, ALC_DEVICE_SPECIFIER), idx
);
+ ++idx;
}
- almtx_unlock(&EnumerationLock);
- return AllDevicesList.Names;
+ /* Ensure the list is double-null termianted. */
+ if(AllDevicesList.Names.empty())
+ AllDevicesList.Names.emplace_back(0);
+ AllDevicesList.Names.emplace_back(0);
+ return AllDevicesList.Names.data();
+ }
case ALC_CAPTURE_DEVICE_SPECIFIER:
- almtx_lock(&EnumerationLock);
- ClearDeviceList(&CaptureDevicesList);
- for(i = 0;i < DriverListSize;i++)
+ { std::lock_guard<std::mutex> _{EnumerationLock};
+ CaptureDevicesList.clear();
+ ALint idx = 0;
+ for(const auto &drv : DriverList)
{
- if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
- DriverList[i].alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE"))
+ if(drv.ALCVer >= MAKE_ALC_VER(1, 1) ||
+ drv.alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE"))
AppendDeviceList(&CaptureDevicesList,
- DriverList[i].alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER), i
+ drv.alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER), idx
);
+ ++idx;
}
- almtx_unlock(&EnumerationLock);
- return CaptureDevicesList.Names;
+ /* Ensure the list is double-null termianted. */
+ if(CaptureDevicesList.Names.empty())
+ CaptureDevicesList.Names.emplace_back(0);
+ CaptureDevicesList.Names.emplace_back(0);
+ return CaptureDevicesList.Names.data();
+ }
case ALC_DEFAULT_DEVICE_SPECIFIER:
- for(i = 0;i < DriverListSize;i++)
- {
- if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
- DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
- return DriverList[i].alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
- }
+ {
+ auto drv = std::find_if(DriverList.cbegin(), DriverList.cend(),
+ [](const DriverIface &drv) -> bool
+ {
+ return drv.ALCVer >= MAKE_ALC_VER(1, 1) ||
+ drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
+ }
+ );
+ if(drv != DriverList.cend())
+ return drv->alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER);
return "";
+ }
case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
- for(i = 0;i < DriverListSize;i++)
- {
- if(DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
- return DriverList[i].alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
- }
+ {
+ auto drv = std::find_if(DriverList.cbegin(), DriverList.cend(),
+ [](const DriverIface &drv) -> bool
+ { return drv.alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"); }
+ );
+ if(drv != DriverList.cend())
+ return drv->alcGetString(nullptr, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
return "";
+ }
case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
- for(i = 0;i < DriverListSize;i++)
- {
- if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
- DriverList[i].alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE"))
- return DriverList[i].alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
- }
+ {
+ auto drv = std::find_if(DriverList.cbegin(), DriverList.cend(),
+ [](const DriverIface &drv) -> bool
+ {
+ return drv.ALCVer >= MAKE_ALC_VER(1, 1) ||
+ drv.alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE");
+ }
+ );
+ if(drv != DriverList.cend())
+ return drv->alcGetString(nullptr, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
return "";
+ }
default:
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_ENUM);
+ LastError.store(ALC_INVALID_ENUM);
break;
}
- return NULL;
+ return nullptr;
}
ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
{
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
return;
}
return DriverList[idx].alcGetIntegerv(device, param, size, values);
}
- if(size <= 0 || values == NULL)
+ if(size <= 0 || values == nullptr)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_VALUE);
+ LastError.store(ALC_INVALID_VALUE);
return;
}
@@ -790,7 +769,7 @@ ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsi
values[0] = alcMinorVersion;
return;
}
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_VALUE);
+ LastError.store(ALC_INVALID_VALUE);
return;
case ALC_ATTRIBUTES_SIZE:
@@ -801,11 +780,11 @@ ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsi
case ALC_MONO_SOURCES:
case ALC_STEREO_SOURCES:
case ALC_CAPTURE_SAMPLES:
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
return;
default:
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_ENUM);
+ LastError.store(ALC_INVALID_ENUM);
return;
}
}
@@ -813,23 +792,24 @@ ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsi
ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize)
{
- ALCdevice *device = NULL;
- ALint idx;
+ ALCdevice *device = nullptr;
+ ALint idx = 0;
if(devicename && devicename[0] == '\0')
- devicename = NULL;
+ devicename = nullptr;
if(devicename)
{
- almtx_lock(&EnumerationLock);
- if(!CaptureDevicesList.Names)
- (void)alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
- idx = GetDriverIndexForName(&CaptureDevicesList, devicename);
- almtx_unlock(&EnumerationLock);
+ { std::lock_guard<std::mutex> _{EnumerationLock};
+ if(CaptureDevicesList.Names.empty())
+ (void)alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER);
+ idx = GetDriverIndexForName(&CaptureDevicesList, devicename);
+ }
+
if(idx < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_VALUE);
+ LastError.store(ALC_INVALID_VALUE);
TRACE("Failed to find driver for name \"%s\"\n", devicename);
- return NULL;
+ return nullptr;
}
TRACE("Found driver %d for name \"%s\"\n", idx, devicename);
device = DriverList[idx].alcCaptureOpenDevice(
@@ -838,28 +818,27 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename,
}
else
{
- int i;
- for(i = 0;i < DriverListSize;i++)
+ for(const auto &drv : DriverList)
{
- if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
- DriverList[i].alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE"))
+ if(drv.ALCVer >= MAKE_ALC_VER(1, 1) ||
+ drv.alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE"))
{
- idx = i;
TRACE("Using default capture device from driver %d\n", idx);
- device = DriverList[idx].alcCaptureOpenDevice(
- NULL, frequency, format, buffersize
+ device = drv.alcCaptureOpenDevice(
+ nullptr, frequency, format, buffersize
);
break;
}
+ ++idx;
}
}
if(device)
{
- if(InsertPtrIntMapEntry(&DeviceIfaceMap, device, idx) != ALC_NO_ERROR)
+ if(DeviceIfaceMap.insert(device, idx) != ALC_NO_ERROR)
{
DriverList[idx].alcCaptureCloseDevice(device);
- device = NULL;
+ device = nullptr;
}
}
@@ -870,14 +849,14 @@ ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
{
ALint idx;
- if(!device || (idx=LookupPtrIntMapKey(&DeviceIfaceMap, device)) < 0)
+ if(!device || (idx=DeviceIfaceMap.lookupByKey(device)) < 0)
{
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
return ALC_FALSE;
}
if(!DriverList[idx].alcCaptureCloseDevice(device))
return ALC_FALSE;
- RemovePtrIntMapKey(&DeviceIfaceMap, device);
+ DeviceIfaceMap.removeByKey(device);
return ALC_TRUE;
}
@@ -885,33 +864,33 @@ ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
{
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx >= 0)
return DriverList[idx].alcCaptureStart(device);
}
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
}
ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
{
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx >= 0)
return DriverList[idx].alcCaptureStop(device);
}
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
}
ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
{
if(device)
{
- ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
+ ALint idx = DeviceIfaceMap.lookupByKey(device);
if(idx >= 0)
return DriverList[idx].alcCaptureSamples(device, buffer, samples);
}
- ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
+ LastError.store(ALC_INVALID_DEVICE);
}
@@ -922,35 +901,35 @@ ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context)
if(!context)
{
- DriverIface *oldiface = altss_get(ThreadCtxDriver);
- if(oldiface && !oldiface->alcSetThreadContext(NULL))
+ DriverIface *oldiface = ThreadCtxDriver;
+ if(oldiface && !oldiface->alcSetThreadContext(nullptr))
return ALC_FALSE;
- altss_set(ThreadCtxDriver, NULL);
+ ThreadCtxDriver = nullptr;
return ALC_TRUE;
}
- idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
+ idx = ContextIfaceMap.lookupByKey(context);
if(idx >= 0)
{
if(DriverList[idx].alcSetThreadContext(context))
{
- DriverIface *oldiface = altss_get(ThreadCtxDriver);
+ DriverIface *oldiface = ThreadCtxDriver;
if(oldiface != &DriverList[idx])
{
- altss_set(ThreadCtxDriver, &DriverList[idx]);
- if(oldiface) oldiface->alcSetThreadContext(NULL);
+ ThreadCtxDriver = &DriverList[idx];
+ if(oldiface) oldiface->alcSetThreadContext(nullptr);
}
return ALC_TRUE;
}
- err = DriverList[idx].alcGetError(NULL);
+ err = DriverList[idx].alcGetError(nullptr);
}
- ATOMIC_STORE_SEQ(&LastError, err);
+ LastError.store(err);
return ALC_FALSE;
}
ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void)
{
- DriverIface *iface = altss_get(ThreadCtxDriver);
+ DriverIface *iface = ThreadCtxDriver;
if(iface) return iface->alcGetThreadContext();
- return NULL;
+ return nullptr;
}
diff --git a/router/router.c b/router/router.cpp
index bff73776..66bf5dd3 100644
--- a/router/router.c
+++ b/router/router.cpp
@@ -13,12 +13,9 @@
#include "version.h"
+std::vector<DriverIface> DriverList;
-DriverIface *DriverList = NULL;
-int DriverListSize = 0;
-static int DriverListSizeMax = 0;
-
-altss_t ThreadCtxDriver;
+thread_local DriverIface *ThreadCtxDriver;
enum LogLevel LogLevel = LogLevel_Error;
FILE *LogFile;
@@ -29,7 +26,6 @@ static void LoadDriverList(void);
BOOL APIENTRY DllMain(HINSTANCE UNUSED(module), DWORD reason, void* UNUSED(reserved))
{
const char *str;
- int i;
switch(reason)
{
@@ -39,7 +35,7 @@ BOOL APIENTRY DllMain(HINSTANCE UNUSED(module), DWORD reason, void* UNUSED(reser
if(str && *str != '\0')
{
FILE *f = fopen(str, "w");
- if(f == NULL)
+ if(f == nullptr)
ERR("Could not open log file: %s\n", str);
else
LogFile = f;
@@ -47,74 +43,49 @@ BOOL APIENTRY DllMain(HINSTANCE UNUSED(module), DWORD reason, void* UNUSED(reser
str = getenv("ALROUTER_LOGLEVEL");
if(str && *str != '\0')
{
- char *end = NULL;
+ char *end = nullptr;
long l = strtol(str, &end, 0);
if(!end || *end != '\0')
ERR("Invalid log level value: %s\n", str);
else if(l < LogLevel_None || l > LogLevel_Trace)
ERR("Log level out of range: %s\n", str);
else
- LogLevel = l;
+ LogLevel = static_cast<enum LogLevel>(l);
}
TRACE("Initializing router v0.1-%s %s\n", ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH);
LoadDriverList();
- altss_create(&ThreadCtxDriver, NULL);
- InitALC();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
- althrd_thread_detach();
break;
case DLL_PROCESS_DETACH:
- ReleaseALC();
- altss_delete(ThreadCtxDriver);
-
- for(i = 0;i < DriverListSize;i++)
- {
- if(DriverList[i].Module)
- FreeLibrary(DriverList[i].Module);
- }
- al_free(DriverList);
- DriverList = NULL;
- DriverListSize = 0;
- DriverListSizeMax = 0;
+ DriverList.clear();
if(LogFile && LogFile != stderr)
fclose(LogFile);
- LogFile = NULL;
+ LogFile = nullptr;
- althrd_deinit();
break;
}
return TRUE;
}
-#ifdef __GNUC__
-#define CAST_FUNC(x) (__typeof(x))
-#else
-#define CAST_FUNC(x) (void*)
-#endif
-
static void AddModule(HMODULE module, const WCHAR *name)
{
- DriverIface newdrv;
- int err = 0;
- int i;
-
- for(i = 0;i < DriverListSize;i++)
+ for(auto &drv : DriverList)
{
- if(DriverList[i].Module == module)
+ if(drv.Module == module)
{
TRACE("Skipping already-loaded module %p\n", module);
FreeLibrary(module);
return;
}
- if(wcscmp(DriverList[i].Name, name) == 0)
+ if(drv.Name == name)
{
TRACE("Skipping similarly-named module %ls\n", name);
FreeLibrary(module);
@@ -122,22 +93,14 @@ static void AddModule(HMODULE module, const WCHAR *name)
}
}
- if(DriverListSize == DriverListSizeMax)
- {
- int newmax = DriverListSizeMax ? DriverListSizeMax<<1 : 4;
- void *newlist = al_calloc(DEF_ALIGN, sizeof(DriverList[0])*newmax);
- if(!newlist) return;
-
- memcpy(newlist, DriverList, DriverListSize*sizeof(DriverList[0]));
- al_free(DriverList);
- DriverList = newlist;
- DriverListSizeMax = newmax;
- }
+ DriverList.emplace_back(name, module);
+ DriverIface &newdrv = DriverList.back();
- memset(&newdrv, 0, sizeof(newdrv));
/* Load required functions. */
+ int err = 0;
#define LOAD_PROC(x) do { \
- newdrv.x = CAST_FUNC(newdrv.x) GetProcAddress(module, #x); \
+ newdrv.x = reinterpret_cast<decltype(newdrv.x)>( \
+ GetProcAddress(module, #x)); \
if(!newdrv.x) \
{ \
ERR("Failed to find entry point for %s in %ls\n", #x, name); \
@@ -241,63 +204,62 @@ static void AddModule(HMODULE module, const WCHAR *name)
if(!err)
{
ALCint alc_ver[2] = { 0, 0 };
- wcsncpy(newdrv.Name, name, 32);
- newdrv.Module = module;
- newdrv.alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &alc_ver[0]);
- newdrv.alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &alc_ver[1]);
- if(newdrv.alcGetError(NULL) == ALC_NO_ERROR)
+ newdrv.alcGetIntegerv(nullptr, ALC_MAJOR_VERSION, 1, &alc_ver[0]);
+ newdrv.alcGetIntegerv(nullptr, ALC_MINOR_VERSION, 1, &alc_ver[1]);
+ if(newdrv.alcGetError(nullptr) == ALC_NO_ERROR)
newdrv.ALCVer = MAKE_ALC_VER(alc_ver[0], alc_ver[1]);
else
newdrv.ALCVer = MAKE_ALC_VER(1, 0);
#undef LOAD_PROC
#define LOAD_PROC(x) do { \
- newdrv.x = CAST_FUNC(newdrv.x) newdrv.alcGetProcAddress(NULL, #x); \
+ newdrv.x = reinterpret_cast<decltype(newdrv.x)>( \
+ newdrv.alcGetProcAddress(nullptr, #x)); \
if(!newdrv.x) \
{ \
ERR("Failed to find entry point for %s in %ls\n", #x, name); \
err = 1; \
} \
} while(0)
- if(newdrv.alcIsExtensionPresent(NULL, "ALC_EXT_thread_local_context"))
+ if(newdrv.alcIsExtensionPresent(nullptr, "ALC_EXT_thread_local_context"))
{
LOAD_PROC(alcSetThreadContext);
LOAD_PROC(alcGetThreadContext);
}
}
- if(!err)
+ if(err)
{
- TRACE("Loaded module %p, %ls, ALC %d.%d\n", module, name,
- newdrv.ALCVer>>8, newdrv.ALCVer&255);
- DriverList[DriverListSize++] = newdrv;
+ DriverList.pop_back();
+ return;
}
+ TRACE("Loaded module %p, %ls, ALC %d.%d\n", module, name,
+ newdrv.ALCVer>>8, newdrv.ALCVer&255);
#undef LOAD_PROC
}
static void SearchDrivers(WCHAR *path)
{
- WCHAR srchPath[MAX_PATH+1] = L"";
WIN32_FIND_DATAW fdata;
- HANDLE srchHdl;
TRACE("Searching for drivers in %ls...\n", path);
- wcsncpy(srchPath, path, MAX_PATH);
- wcsncat(srchPath, L"\\*oal.dll", MAX_PATH - lstrlenW(srchPath));
- srchHdl = FindFirstFileW(srchPath, &fdata);
+ std::wstring srchPath = path;
+ srchPath += L"\\*oal.dll";
+
+ HANDLE srchHdl = FindFirstFileW(srchPath.c_str(), &fdata);
if(srchHdl != INVALID_HANDLE_VALUE)
{
do {
HMODULE mod;
- wcsncpy(srchPath, path, MAX_PATH);
- wcsncat(srchPath, L"\\", MAX_PATH - lstrlenW(srchPath));
- wcsncat(srchPath, fdata.cFileName, MAX_PATH - lstrlenW(srchPath));
- TRACE("Found %ls\n", srchPath);
+ srchPath = path;
+ srchPath += L"\\";
+ srchPath += fdata.cFileName;
+ TRACE("Found %ls\n", srchPath.c_str());
- mod = LoadLibraryW(srchPath);
+ mod = LoadLibraryW(srchPath.c_str());
if(!mod)
- WARN("Could not load %ls\n", srchPath);
+ WARN("Could not load %ls\n", srchPath.c_str());
else
AddModule(mod, fdata.cFileName);
} while(FindNextFileW(srchHdl, &fdata));
@@ -307,7 +269,7 @@ static void SearchDrivers(WCHAR *path)
static WCHAR *strrchrW(WCHAR *str, WCHAR ch)
{
- WCHAR *res = NULL;
+ WCHAR *res = nullptr;
while(str && *str != '\0')
{
if(*str == ch)
@@ -319,7 +281,7 @@ static WCHAR *strrchrW(WCHAR *str, WCHAR ch)
static int GetLoadedModuleDirectory(const WCHAR *name, WCHAR *moddir, DWORD length)
{
- HMODULE module = NULL;
+ HMODULE module = nullptr;
WCHAR *sep0, *sep1;
if(name)
@@ -359,7 +321,7 @@ void LoadDriverList(void)
cwd_path[len-1] = '\0';
TRACE("Got current working directory %ls\n", cwd_path);
- if(GetLoadedModuleDirectory(NULL, proc_path, MAX_PATH))
+ if(GetLoadedModuleDirectory(nullptr, proc_path, MAX_PATH))
TRACE("Got proc path %ls\n", proc_path);
GetSystemDirectoryW(sys_path, MAX_PATH);
@@ -388,38 +350,28 @@ void LoadDriverList(void)
}
-void InitPtrIntMap(PtrIntMap *map)
-{
- map->keys = NULL;
- map->values = NULL;
- map->size = 0;
- map->capacity = 0;
- RWLockInit(&map->lock);
-}
-
-void ResetPtrIntMap(PtrIntMap *map)
+PtrIntMap::~PtrIntMap()
{
- WriteLock(&map->lock);
- al_free(map->keys);
- map->keys = NULL;
- map->values = NULL;
- map->size = 0;
- map->capacity = 0;
- WriteUnlock(&map->lock);
+ std::lock_guard<std::mutex> maplock{mLock};
+ al_free(mKeys);
+ mKeys = nullptr;
+ mValues = nullptr;
+ mSize = 0;
+ mCapacity = 0;
}
-ALenum InsertPtrIntMapEntry(PtrIntMap *map, ALvoid *key, ALint value)
+ALenum PtrIntMap::insert(ALvoid *key, ALint value)
{
ALsizei pos = 0;
- WriteLock(&map->lock);
- if(map->size > 0)
+ std::lock_guard<std::mutex> maplock{mLock};
+ if(mSize > 0)
{
- ALsizei count = map->size;
+ ALsizei count = mSize;
do {
ALsizei step = count>>1;
ALsizei i = pos+step;
- if(!(map->keys[i] < key))
+ if(mKeys[i] >= key)
count = step;
else
{
@@ -429,63 +381,60 @@ ALenum InsertPtrIntMapEntry(PtrIntMap *map, ALvoid *key, ALint value)
} while(count > 0);
}
- if(pos == map->size || map->keys[pos] != key)
+ if(pos == mSize || mKeys[pos] != key)
{
- if(map->size == map->capacity)
+ if(mSize == mCapacity)
{
- ALvoid **keys = NULL;
- ALint *values;
+ ALvoid **newkeys = nullptr;
+ ALint *newvalues;
ALsizei newcap;
- newcap = (map->capacity ? (map->capacity<<1) : 4);
- if(newcap > map->capacity)
- keys = al_calloc(16, (sizeof(map->keys[0])+sizeof(map->values[0]))*newcap);
- if(!keys)
- {
- WriteUnlock(&map->lock);
+ newcap = (mCapacity ? (mCapacity<<1) : 4);
+ if(newcap > mCapacity)
+ newkeys = reinterpret_cast<ALvoid**>(
+ al_calloc(16, (sizeof(mKeys[0])+sizeof(mValues[0]))*newcap)
+ );
+ if(!newkeys)
return AL_OUT_OF_MEMORY;
- }
- values = (ALint*)&keys[newcap];
+ newvalues = (ALint*)&newkeys[newcap];
- if(map->keys)
+ if(mKeys)
{
- memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
- memcpy(values, map->values, map->size*sizeof(map->values[0]));
+ memcpy(newkeys, mKeys, mSize*sizeof(mKeys[0]));
+ memcpy(newvalues, mValues, mSize*sizeof(mValues[0]));
}
- al_free(map->keys);
- map->keys = keys;
- map->values = values;
- map->capacity = newcap;
+ al_free(mKeys);
+ mKeys = newkeys;
+ mValues = newvalues;
+ mCapacity = newcap;
}
- if(pos < map->size)
+ if(pos < mSize)
{
- memmove(&map->keys[pos+1], &map->keys[pos],
- (map->size-pos)*sizeof(map->keys[0]));
- memmove(&map->values[pos+1], &map->values[pos],
- (map->size-pos)*sizeof(map->values[0]));
+ memmove(&mKeys[pos+1], &mKeys[pos], (mSize-pos)*sizeof(mKeys[0]));
+ memmove(&mValues[pos+1], &mValues[pos], (mSize-pos)*sizeof(mValues[0]));
}
- map->size++;
+ mSize++;
}
- map->keys[pos] = key;
- map->values[pos] = value;
- WriteUnlock(&map->lock);
+ mKeys[pos] = key;
+ mValues[pos] = value;
return AL_NO_ERROR;
}
-ALint RemovePtrIntMapKey(PtrIntMap *map, ALvoid *key)
+ALint PtrIntMap::removeByKey(ALvoid *key)
{
ALint ret = -1;
- WriteLock(&map->lock);
- if(map->size > 0)
+
+ std::lock_guard<std::mutex> maplock{mLock};
+ if(mSize > 0)
{
ALsizei pos = 0;
- ALsizei count = map->size;
+ ALsizei count = mSize;
do {
ALsizei step = count>>1;
ALsizei i = pos+step;
- if(!(map->keys[i] < key))
+ if(mKeys[i] >= key)
count = step;
else
{
@@ -493,35 +442,33 @@ ALint RemovePtrIntMapKey(PtrIntMap *map, ALvoid *key)
count -= step+1;
}
} while(count > 0);
- if(pos < map->size && map->keys[pos] == key)
+ if(pos < mSize && mKeys[pos] == key)
{
- ret = map->values[pos];
- if(pos < map->size-1)
+ ret = mValues[pos];
+ if(pos < mSize-1)
{
- memmove(&map->keys[pos], &map->keys[pos+1],
- (map->size-1-pos)*sizeof(map->keys[0]));
- memmove(&map->values[pos], &map->values[pos+1],
- (map->size-1-pos)*sizeof(map->values[0]));
+ memmove(&mKeys[pos], &mKeys[pos+1], (mSize-1-pos)*sizeof(mKeys[0]));
+ memmove(&mValues[pos], &mValues[pos+1], (mSize-1-pos)*sizeof(mValues[0]));
}
- map->size--;
+ mSize--;
}
}
- WriteUnlock(&map->lock);
return ret;
}
-ALint LookupPtrIntMapKey(PtrIntMap *map, ALvoid *key)
+ALint PtrIntMap::lookupByKey(ALvoid* key)
{
ALint ret = -1;
- ReadLock(&map->lock);
- if(map->size > 0)
+
+ std::lock_guard<std::mutex> maplock{mLock};
+ if(mSize > 0)
{
ALsizei pos = 0;
- ALsizei count = map->size;
+ ALsizei count = mSize;
do {
ALsizei step = count>>1;
ALsizei i = pos+step;
- if(!(map->keys[i] < key))
+ if(mKeys[i] >= key)
count = step;
else
{
@@ -529,9 +476,8 @@ ALint LookupPtrIntMapKey(PtrIntMap *map, ALvoid *key)
count -= step+1;
}
} while(count > 0);
- if(pos < map->size && map->keys[pos] == key)
- ret = map->values[pos];
+ if(pos < mSize && mKeys[pos] == key)
+ ret = mValues[pos];
}
- ReadUnlock(&map->lock);
return ret;
}
diff --git a/router/router.h b/router/router.h
index 32a91dcb..d2574e74 100644
--- a/router/router.h
+++ b/router/router.h
@@ -7,12 +7,14 @@
#include <stdio.h>
+#include <vector>
+#include <string>
+#include <atomic>
+#include <mutex>
+
#include "AL/alc.h"
#include "AL/al.h"
#include "AL/alext.h"
-#include "atomic.h"
-#include "rwlock.h"
-#include "threads.h"
#ifndef UNUSED
@@ -29,138 +31,143 @@
#define MAKE_ALC_VER(major, minor) (((major)<<8) | (minor))
-typedef struct DriverIface {
- WCHAR Name[32];
- HMODULE Module;
- int ALCVer;
-
- LPALCCREATECONTEXT alcCreateContext;
- LPALCMAKECONTEXTCURRENT alcMakeContextCurrent;
- LPALCPROCESSCONTEXT alcProcessContext;
- LPALCSUSPENDCONTEXT alcSuspendContext;
- LPALCDESTROYCONTEXT alcDestroyContext;
- LPALCGETCURRENTCONTEXT alcGetCurrentContext;
- LPALCGETCONTEXTSDEVICE alcGetContextsDevice;
- LPALCOPENDEVICE alcOpenDevice;
- LPALCCLOSEDEVICE alcCloseDevice;
- LPALCGETERROR alcGetError;
- LPALCISEXTENSIONPRESENT alcIsExtensionPresent;
- LPALCGETPROCADDRESS alcGetProcAddress;
- LPALCGETENUMVALUE alcGetEnumValue;
- LPALCGETSTRING alcGetString;
- LPALCGETINTEGERV alcGetIntegerv;
- LPALCCAPTUREOPENDEVICE alcCaptureOpenDevice;
- LPALCCAPTURECLOSEDEVICE alcCaptureCloseDevice;
- LPALCCAPTURESTART alcCaptureStart;
- LPALCCAPTURESTOP alcCaptureStop;
- LPALCCAPTURESAMPLES alcCaptureSamples;
-
- PFNALCSETTHREADCONTEXTPROC alcSetThreadContext;
- PFNALCGETTHREADCONTEXTPROC alcGetThreadContext;
-
- LPALENABLE alEnable;
- LPALDISABLE alDisable;
- LPALISENABLED alIsEnabled;
- LPALGETSTRING alGetString;
- LPALGETBOOLEANV alGetBooleanv;
- LPALGETINTEGERV alGetIntegerv;
- LPALGETFLOATV alGetFloatv;
- LPALGETDOUBLEV alGetDoublev;
- LPALGETBOOLEAN alGetBoolean;
- LPALGETINTEGER alGetInteger;
- LPALGETFLOAT alGetFloat;
- LPALGETDOUBLE alGetDouble;
- LPALGETERROR alGetError;
- LPALISEXTENSIONPRESENT alIsExtensionPresent;
- LPALGETPROCADDRESS alGetProcAddress;
- LPALGETENUMVALUE alGetEnumValue;
- LPALLISTENERF alListenerf;
- LPALLISTENER3F alListener3f;
- LPALLISTENERFV alListenerfv;
- LPALLISTENERI alListeneri;
- LPALLISTENER3I alListener3i;
- LPALLISTENERIV alListeneriv;
- LPALGETLISTENERF alGetListenerf;
- LPALGETLISTENER3F alGetListener3f;
- LPALGETLISTENERFV alGetListenerfv;
- LPALGETLISTENERI alGetListeneri;
- LPALGETLISTENER3I alGetListener3i;
- LPALGETLISTENERIV alGetListeneriv;
- LPALGENSOURCES alGenSources;
- LPALDELETESOURCES alDeleteSources;
- LPALISSOURCE alIsSource;
- LPALSOURCEF alSourcef;
- LPALSOURCE3F alSource3f;
- LPALSOURCEFV alSourcefv;
- LPALSOURCEI alSourcei;
- LPALSOURCE3I alSource3i;
- LPALSOURCEIV alSourceiv;
- LPALGETSOURCEF alGetSourcef;
- LPALGETSOURCE3F alGetSource3f;
- LPALGETSOURCEFV alGetSourcefv;
- LPALGETSOURCEI alGetSourcei;
- LPALGETSOURCE3I alGetSource3i;
- LPALGETSOURCEIV alGetSourceiv;
- LPALSOURCEPLAYV alSourcePlayv;
- LPALSOURCESTOPV alSourceStopv;
- LPALSOURCEREWINDV alSourceRewindv;
- LPALSOURCEPAUSEV alSourcePausev;
- LPALSOURCEPLAY alSourcePlay;
- LPALSOURCESTOP alSourceStop;
- LPALSOURCEREWIND alSourceRewind;
- LPALSOURCEPAUSE alSourcePause;
- LPALSOURCEQUEUEBUFFERS alSourceQueueBuffers;
- LPALSOURCEUNQUEUEBUFFERS alSourceUnqueueBuffers;
- LPALGENBUFFERS alGenBuffers;
- LPALDELETEBUFFERS alDeleteBuffers;
- LPALISBUFFER alIsBuffer;
- LPALBUFFERF alBufferf;
- LPALBUFFER3F alBuffer3f;
- LPALBUFFERFV alBufferfv;
- LPALBUFFERI alBufferi;
- LPALBUFFER3I alBuffer3i;
- LPALBUFFERIV alBufferiv;
- LPALGETBUFFERF alGetBufferf;
- LPALGETBUFFER3F alGetBuffer3f;
- LPALGETBUFFERFV alGetBufferfv;
- LPALGETBUFFERI alGetBufferi;
- LPALGETBUFFER3I alGetBuffer3i;
- LPALGETBUFFERIV alGetBufferiv;
- LPALBUFFERDATA alBufferData;
- LPALDOPPLERFACTOR alDopplerFactor;
- LPALDOPPLERVELOCITY alDopplerVelocity;
- LPALSPEEDOFSOUND alSpeedOfSound;
- LPALDISTANCEMODEL alDistanceModel;
-} DriverIface;
-
-extern DriverIface *DriverList;
-extern int DriverListSize;
-
-extern altss_t ThreadCtxDriver;
-typedef ATOMIC(DriverIface*) atomic_DriverIfacePtr;
-extern atomic_DriverIfacePtr CurrentCtxDriver;
-
-
-typedef struct PtrIntMap {
- ALvoid **keys;
- /* Shares memory with keys. */
- ALint *values;
+struct DriverIface {
+ std::wstring Name;
+ HMODULE Module{nullptr};
+ int ALCVer{0};
+
+ LPALCCREATECONTEXT alcCreateContext{nullptr};
+ LPALCMAKECONTEXTCURRENT alcMakeContextCurrent{nullptr};
+ LPALCPROCESSCONTEXT alcProcessContext{nullptr};
+ LPALCSUSPENDCONTEXT alcSuspendContext{nullptr};
+ LPALCDESTROYCONTEXT alcDestroyContext{nullptr};
+ LPALCGETCURRENTCONTEXT alcGetCurrentContext{nullptr};
+ LPALCGETCONTEXTSDEVICE alcGetContextsDevice{nullptr};
+ LPALCOPENDEVICE alcOpenDevice{nullptr};
+ LPALCCLOSEDEVICE alcCloseDevice{nullptr};
+ LPALCGETERROR alcGetError{nullptr};
+ LPALCISEXTENSIONPRESENT alcIsExtensionPresent{nullptr};
+ LPALCGETPROCADDRESS alcGetProcAddress{nullptr};
+ LPALCGETENUMVALUE alcGetEnumValue{nullptr};
+ LPALCGETSTRING alcGetString{nullptr};
+ LPALCGETINTEGERV alcGetIntegerv{nullptr};
+ LPALCCAPTUREOPENDEVICE alcCaptureOpenDevice{nullptr};
+ LPALCCAPTURECLOSEDEVICE alcCaptureCloseDevice{nullptr};
+ LPALCCAPTURESTART alcCaptureStart{nullptr};
+ LPALCCAPTURESTOP alcCaptureStop{nullptr};
+ LPALCCAPTURESAMPLES alcCaptureSamples{nullptr};
+
+ PFNALCSETTHREADCONTEXTPROC alcSetThreadContext{nullptr};
+ PFNALCGETTHREADCONTEXTPROC alcGetThreadContext{nullptr};
+
+ LPALENABLE alEnable{nullptr};
+ LPALDISABLE alDisable{nullptr};
+ LPALISENABLED alIsEnabled{nullptr};
+ LPALGETSTRING alGetString{nullptr};
+ LPALGETBOOLEANV alGetBooleanv{nullptr};
+ LPALGETINTEGERV alGetIntegerv{nullptr};
+ LPALGETFLOATV alGetFloatv{nullptr};
+ LPALGETDOUBLEV alGetDoublev{nullptr};
+ LPALGETBOOLEAN alGetBoolean{nullptr};
+ LPALGETINTEGER alGetInteger{nullptr};
+ LPALGETFLOAT alGetFloat{nullptr};
+ LPALGETDOUBLE alGetDouble{nullptr};
+ LPALGETERROR alGetError{nullptr};
+ LPALISEXTENSIONPRESENT alIsExtensionPresent{nullptr};
+ LPALGETPROCADDRESS alGetProcAddress{nullptr};
+ LPALGETENUMVALUE alGetEnumValue{nullptr};
+ LPALLISTENERF alListenerf{nullptr};
+ LPALLISTENER3F alListener3f{nullptr};
+ LPALLISTENERFV alListenerfv{nullptr};
+ LPALLISTENERI alListeneri{nullptr};
+ LPALLISTENER3I alListener3i{nullptr};
+ LPALLISTENERIV alListeneriv{nullptr};
+ LPALGETLISTENERF alGetListenerf{nullptr};
+ LPALGETLISTENER3F alGetListener3f{nullptr};
+ LPALGETLISTENERFV alGetListenerfv{nullptr};
+ LPALGETLISTENERI alGetListeneri{nullptr};
+ LPALGETLISTENER3I alGetListener3i{nullptr};
+ LPALGETLISTENERIV alGetListeneriv{nullptr};
+ LPALGENSOURCES alGenSources{nullptr};
+ LPALDELETESOURCES alDeleteSources{nullptr};
+ LPALISSOURCE alIsSource{nullptr};
+ LPALSOURCEF alSourcef{nullptr};
+ LPALSOURCE3F alSource3f{nullptr};
+ LPALSOURCEFV alSourcefv{nullptr};
+ LPALSOURCEI alSourcei{nullptr};
+ LPALSOURCE3I alSource3i{nullptr};
+ LPALSOURCEIV alSourceiv{nullptr};
+ LPALGETSOURCEF alGetSourcef{nullptr};
+ LPALGETSOURCE3F alGetSource3f{nullptr};
+ LPALGETSOURCEFV alGetSourcefv{nullptr};
+ LPALGETSOURCEI alGetSourcei{nullptr};
+ LPALGETSOURCE3I alGetSource3i{nullptr};
+ LPALGETSOURCEIV alGetSourceiv{nullptr};
+ LPALSOURCEPLAYV alSourcePlayv{nullptr};
+ LPALSOURCESTOPV alSourceStopv{nullptr};
+ LPALSOURCEREWINDV alSourceRewindv{nullptr};
+ LPALSOURCEPAUSEV alSourcePausev{nullptr};
+ LPALSOURCEPLAY alSourcePlay{nullptr};
+ LPALSOURCESTOP alSourceStop{nullptr};
+ LPALSOURCEREWIND alSourceRewind{nullptr};
+ LPALSOURCEPAUSE alSourcePause{nullptr};
+ LPALSOURCEQUEUEBUFFERS alSourceQueueBuffers{nullptr};
+ LPALSOURCEUNQUEUEBUFFERS alSourceUnqueueBuffers{nullptr};
+ LPALGENBUFFERS alGenBuffers{nullptr};
+ LPALDELETEBUFFERS alDeleteBuffers{nullptr};
+ LPALISBUFFER alIsBuffer{nullptr};
+ LPALBUFFERF alBufferf{nullptr};
+ LPALBUFFER3F alBuffer3f{nullptr};
+ LPALBUFFERFV alBufferfv{nullptr};
+ LPALBUFFERI alBufferi{nullptr};
+ LPALBUFFER3I alBuffer3i{nullptr};
+ LPALBUFFERIV alBufferiv{nullptr};
+ LPALGETBUFFERF alGetBufferf{nullptr};
+ LPALGETBUFFER3F alGetBuffer3f{nullptr};
+ LPALGETBUFFERFV alGetBufferfv{nullptr};
+ LPALGETBUFFERI alGetBufferi{nullptr};
+ LPALGETBUFFER3I alGetBuffer3i{nullptr};
+ LPALGETBUFFERIV alGetBufferiv{nullptr};
+ LPALBUFFERDATA alBufferData{nullptr};
+ LPALDOPPLERFACTOR alDopplerFactor{nullptr};
+ LPALDOPPLERVELOCITY alDopplerVelocity{nullptr};
+ LPALSPEEDOFSOUND alSpeedOfSound{nullptr};
+ LPALDISTANCEMODEL alDistanceModel{nullptr};
+
+ DriverIface(std::wstring name, HMODULE mod)
+ : Name(std::move(name)), Module(mod)
+ { }
+ ~DriverIface()
+ {
+ if(Module)
+ FreeLibrary(Module);
+ Module = nullptr;
+ }
+};
+
+extern std::vector<DriverIface> DriverList;
- ALsizei size;
- ALsizei capacity;
- RWLock lock;
-} PtrIntMap;
-#define PTRINTMAP_STATIC_INITIALIZE { NULL, NULL, 0, 0, RWLOCK_STATIC_INITIALIZE }
+extern thread_local DriverIface *ThreadCtxDriver;
+extern std::atomic<DriverIface*> CurrentCtxDriver;
-void InitPtrIntMap(PtrIntMap *map);
-void ResetPtrIntMap(PtrIntMap *map);
-ALenum InsertPtrIntMapEntry(PtrIntMap *map, ALvoid *key, ALint value);
-ALint RemovePtrIntMapKey(PtrIntMap *map, ALvoid *key);
-ALint LookupPtrIntMapKey(PtrIntMap *map, ALvoid *key);
+class PtrIntMap {
+ ALvoid **mKeys{nullptr};
+ /* Shares memory with keys. */
+ ALint *mValues{nullptr};
+
+ ALsizei mSize{0};
+ ALsizei mCapacity{0};
+ std::mutex mLock;
-void InitALC(void);
-void ReleaseALC(void);
+public:
+ PtrIntMap() = default;
+ ~PtrIntMap();
+
+ ALenum insert(ALvoid *key, ALint value);
+ ALint removeByKey(ALvoid *key);
+ ALint lookupByKey(ALvoid *key);
+};
enum LogLevel {
diff --git a/utils/alsoft-config/mainwindow.cpp b/utils/alsoft-config/mainwindow.cpp
index 110fe4ed..56ac4f3f 100644
--- a/utils/alsoft-config/mainwindow.cpp
+++ b/utils/alsoft-config/mainwindow.cpp
@@ -916,7 +916,7 @@ void MainWindow::saveConfig(const QString &fname) const
settings.setValue("channels", getValueFromName(speakerModeList, ui->channelConfigCombo->currentText()));
uint rate = ui->sampleRateCombo->currentText().toUInt();
- if(!(rate > 0))
+ if(rate <= 0)
settings.setValue("frequency", QString());
else
settings.setValue("frequency", rate);
diff --git a/utils/makehrtf.c b/utils/makehrtf.c
index 0bd36849..eb174c8a 100644
--- a/utils/makehrtf.c
+++ b/utils/makehrtf.c
@@ -945,7 +945,7 @@ static inline uint dither_rng(uint *seed)
// Performs a triangular probability density function dither. The input samples
// should be normalized (-1 to +1).
-static void TpdfDither(double *restrict out, const double *restrict in, const double scale,
+static void TpdfDither(double *RESTRICT out, const double *RESTRICT in, const double scale,
const int count, const int step, uint *seed)
{
static const double PRNG_SCALE = 1.0 / UINT_MAX;