Use constructors/destructors with ALCdevice

As with ALCcontext, this is really ALCdevice_struct because of the way it's
declared in the public header.
This commit is contained in:
Chris Robinson 2018-11-18 07:33:42 -08:00
parent 1bc88ed751
commit 336b7b7799
2 changed files with 139 additions and 219 deletions

View File

@ -2388,154 +2388,101 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
}
static void InitDevice(ALCdevice *device, enum DeviceType type)
ALCdevice_struct::ALCdevice_struct(DeviceType type)
: Type{type}
{
ALsizei i;
VECTOR_INIT(HrtfList);
InitRef(&device->ref, 1);
ATOMIC_INIT(&device->Connected, ALC_TRUE);
device->Type = type;
ATOMIC_INIT(&device->LastError, ALC_NO_ERROR);
VECTOR_INIT(BufferList);
almtx_init(&BufferLock, almtx_plain);
device->Flags = 0;
device->Render_Mode = NormalRender;
device->AvgSpeakerDist = 0.0f;
device->LimiterState = ALC_DONT_CARE_SOFT;
VECTOR_INIT(EffectList);
almtx_init(&EffectLock, almtx_plain);
ATOMIC_INIT(&device->ContextList, static_cast<ALCcontext*>(nullptr));
VECTOR_INIT(FilterList);
almtx_init(&FilterLock, almtx_plain);
device->ClockBase = 0;
device->SamplesDone = 0;
device->FixedLatency = 0;
device->SourcesMax = 0;
device->AuxiliaryEffectSlotMax = 0;
device->NumAuxSends = 0;
device->Dry.Buffer = nullptr;
device->Dry.NumChannels = 0;
device->FOAOut.Buffer = nullptr;
device->FOAOut.NumChannels = 0;
device->RealOut.Buffer = nullptr;
device->RealOut.NumChannels = 0;
device->DeviceName = nullptr;
for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
{
device->ChannelDelay[i].Gain = 1.0f;
device->ChannelDelay[i].Length = 0;
device->ChannelDelay[i].Buffer = nullptr;
}
device->HrtfName = nullptr;
VECTOR_INIT(device->HrtfList);
device->HrtfHandle = nullptr;
device->Hrtf = nullptr;
device->Bs2b = nullptr;
device->Uhj_Encoder = nullptr;
device->AmbiDecoder = nullptr;
device->AmbiUp = nullptr;
device->Stablizer = nullptr;
device->Limiter = nullptr;
VECTOR_INIT(device->BufferList);
almtx_init(&device->BufferLock, almtx_plain);
VECTOR_INIT(device->EffectList);
almtx_init(&device->EffectLock, almtx_plain);
VECTOR_INIT(device->FilterList);
almtx_init(&device->FilterLock, almtx_plain);
almtx_init(&device->BackendLock, almtx_plain);
device->Backend = nullptr;
ATOMIC_INIT(&device->next, static_cast<ALCdevice*>(nullptr));
almtx_init(&BackendLock, almtx_plain);
}
/* FreeDevice
/* ALCdevice_struct::~ALCdevice_struct
*
* Frees the device structure, and destroys any objects the app failed to
* delete. Called once there's no more references on the device.
*/
static ALCvoid FreeDevice(ALCdevice *device)
ALCdevice_struct::~ALCdevice_struct()
{
ALsizei i;
TRACE("%p\n", this);
TRACE("%p\n", device);
if(Backend)
DELETE_OBJ(Backend);
Backend = nullptr;
if(device->Backend)
DELETE_OBJ(device->Backend);
device->Backend = nullptr;
almtx_destroy(&BackendLock);
almtx_destroy(&device->BackendLock);
ReleaseALBuffers(device);
ReleaseALBuffers(this);
#define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
VECTOR_FOR_EACH(BufferSubList, device->BufferList, FREE_BUFFERSUBLIST);
VECTOR_FOR_EACH(BufferSubList, BufferList, FREE_BUFFERSUBLIST);
#undef FREE_BUFFERSUBLIST
VECTOR_DEINIT(device->BufferList);
almtx_destroy(&device->BufferLock);
VECTOR_DEINIT(BufferList);
almtx_destroy(&BufferLock);
ReleaseALEffects(device);
ReleaseALEffects(this);
#define FREE_EFFECTSUBLIST(x) al_free((x)->Effects)
VECTOR_FOR_EACH(EffectSubList, device->EffectList, FREE_EFFECTSUBLIST);
VECTOR_FOR_EACH(EffectSubList, EffectList, FREE_EFFECTSUBLIST);
#undef FREE_EFFECTSUBLIST
VECTOR_DEINIT(device->EffectList);
almtx_destroy(&device->EffectLock);
VECTOR_DEINIT(EffectList);
almtx_destroy(&EffectLock);
ReleaseALFilters(device);
ReleaseALFilters(this);
#define FREE_FILTERSUBLIST(x) al_free((x)->Filters)
VECTOR_FOR_EACH(FilterSubList, device->FilterList, FREE_FILTERSUBLIST);
VECTOR_FOR_EACH(FilterSubList, FilterList, FREE_FILTERSUBLIST);
#undef FREE_FILTERSUBLIST
VECTOR_DEINIT(device->FilterList);
almtx_destroy(&device->FilterLock);
VECTOR_DEINIT(FilterList);
almtx_destroy(&FilterLock);
al_free(device->HrtfName);
device->HrtfName = nullptr;
FreeHrtfList(&device->HrtfList);
if(device->HrtfHandle)
Hrtf_DecRef(device->HrtfHandle);
device->HrtfHandle = nullptr;
al_free(device->Hrtf);
device->Hrtf = nullptr;
al_free(HrtfName);
HrtfName = nullptr;
FreeHrtfList(&HrtfList);
if(HrtfHandle)
Hrtf_DecRef(HrtfHandle);
HrtfHandle = nullptr;
al_free(Hrtf);
Hrtf = nullptr;
al_free(device->Bs2b);
device->Bs2b = nullptr;
al_free(Bs2b);
Bs2b = nullptr;
al_free(device->Uhj_Encoder);
device->Uhj_Encoder = nullptr;
al_free(Uhj_Encoder);
Uhj_Encoder = nullptr;
bformatdec_free(&device->AmbiDecoder);
ambiup_free(&device->AmbiUp);
bformatdec_free(&AmbiDecoder);
ambiup_free(&AmbiUp);
al_free(device->Stablizer);
device->Stablizer = nullptr;
al_free(Stablizer);
Stablizer = nullptr;
al_free(device->Limiter);
device->Limiter = nullptr;
al_free(Limiter);
Limiter = nullptr;
al_free(device->ChannelDelay[0].Buffer);
for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
al_free(ChannelDelay[0].Buffer);
for(ALsizei i{0};i < MAX_OUTPUT_CHANNELS;i++)
{
device->ChannelDelay[i].Gain = 1.0f;
device->ChannelDelay[i].Length = 0;
device->ChannelDelay[i].Buffer = nullptr;
ChannelDelay[i].Gain = 1.0f;
ChannelDelay[i].Length = 0;
ChannelDelay[i].Buffer = nullptr;
}
al_free(device->DeviceName);
device->DeviceName = nullptr;
al_free(DeviceName);
DeviceName = nullptr;
al_free(device->Dry.Buffer);
device->Dry.Buffer = nullptr;
device->Dry.NumChannels = 0;
device->FOAOut.Buffer = nullptr;
device->FOAOut.NumChannels = 0;
device->RealOut.Buffer = nullptr;
device->RealOut.NumChannels = 0;
al_free(device);
al_free(Dry.Buffer);
Dry.Buffer = nullptr;
Dry.NumChannels = 0;
FOAOut.Buffer = nullptr;
FOAOut.NumChannels = 0;
RealOut.Buffer = nullptr;
RealOut.NumChannels = 0;
}
@ -2551,7 +2498,7 @@ void ALCdevice_DecRef(ALCdevice *device)
uint ref;
ref = DecrementRef(&device->ref);
TRACEREF("%p decreasing refcount to %u\n", device, ref);
if(ref == 0) FreeDevice(device);
if(ref == 0) delete device;
}
/* VerifyDevice
@ -3954,15 +3901,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
))
deviceName = nullptr;
auto device = static_cast<ALCdevice*>(al_calloc(16, sizeof(ALCdevice)));
if(!device)
{
alcSetError(nullptr, ALC_OUT_OF_MEMORY);
return nullptr;
}
//Validate device
InitDevice(device, Playback);
auto device = new ALCdevice{Playback};
//Set output format
device->FmtChans = DevFmtChannelsDefault;
@ -4074,7 +4013,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
device->Backend = PlaybackBackend.getFactory().createBackend(device, ALCbackend_Playback);
if(!device->Backend)
{
FreeDevice(device);
delete device;
alcSetError(nullptr, ALC_OUT_OF_MEMORY);
return nullptr;
}
@ -4083,7 +4022,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
ALCenum err{V(device->Backend,open)(deviceName)};
if(err != ALC_NO_ERROR)
{
FreeDevice(device);
delete device;
alcSetError(nullptr, err);
return nullptr;
}
@ -4193,22 +4132,14 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName,
if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0))
deviceName = nullptr;
auto device = static_cast<ALCdevice*>(al_calloc(16, sizeof(ALCdevice)));
if(!device)
{
alcSetError(nullptr, ALC_OUT_OF_MEMORY);
return nullptr;
}
//Validate device
InitDevice(device, Capture);
auto device = new ALCdevice{Capture};
device->Frequency = frequency;
device->Flags |= DEVICE_FREQUENCY_REQUEST;
if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE)
{
FreeDevice(device);
delete device;
alcSetError(nullptr, ALC_INVALID_ENUM);
return nullptr;
}
@ -4224,7 +4155,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName,
device->Backend = CaptureBackend.getFactory().createBackend(device, ALCbackend_Capture);
if(!device->Backend)
{
FreeDevice(device);
delete device;
alcSetError(nullptr, ALC_OUT_OF_MEMORY);
return nullptr;
}
@ -4236,7 +4167,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName,
ALCenum err{V(device->Backend,open)(deviceName)};
if(err != ALC_NO_ERROR)
{
FreeDevice(device);
delete device;
alcSetError(nullptr, err);
return nullptr;
}
@ -4371,15 +4302,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
return nullptr;
}
auto device = static_cast<ALCdevice*>(al_calloc(16, sizeof(ALCdevice)));
if(!device)
{
alcSetError(nullptr, ALC_OUT_OF_MEMORY);
return nullptr;
}
//Validate device
InitDevice(device, Loopback);
auto device = new ALCdevice{Loopback};
device->SourcesMax = 256;
device->AuxiliaryEffectSlotMax = 64;

View File

@ -16,6 +16,9 @@
#include <intrin.h>
#endif
#include <vector>
#include <string>
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
@ -29,14 +32,10 @@
#include "threads.h"
#ifndef __cplusplus
#define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
#else
template<typename T, size_t N>
constexpr inline size_t countof(const T(&)[N]) noexcept
{ return N; }
#define COUNTOF countof
#endif
#if defined(_WIN64)
#define SZFMT "%I64u"
@ -104,13 +103,6 @@ constexpr inline size_t countof(const T(&)[N]) noexcept
#define FAM_SIZE(T, M, N) (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N))
#ifdef __cplusplus
#include <vector>
#include <string>
extern "C" {
#endif
typedef ALint64SOFT ALint64;
typedef ALuint64SOFT ALuint64;
@ -547,9 +539,9 @@ TYPEDEF_VECTOR(EnumeratedHrtf, vector_EnumeratedHrtf)
#define MAX_DELAY_LENGTH 1024
typedef struct DistanceComp {
ALfloat Gain;
ALsizei Length; /* Valid range is [0...MAX_DELAY_LENGTH). */
ALfloat *Buffer;
ALfloat Gain{1.0f};
ALsizei Length{0}; /* Valid range is [0...MAX_DELAY_LENGTH). */
ALfloat *Buffer{nullptr};
} DistanceComp;
/* Size for temporary storage of buffer data, in ALfloats. Larger values need
@ -560,109 +552,109 @@ typedef struct DistanceComp {
#define BUFFERSIZE 2048
typedef struct MixParams {
AmbiConfig Ambi;
AmbiConfig Ambi{};
/* Number of coefficients in each Ambi.Coeffs to mix together (4 for first-
* order, 9 for second-order, etc). If the count is 0, Ambi.Map is used
* instead to map each output to a coefficient index.
*/
ALsizei CoeffCount;
ALsizei CoeffCount{0};
ALfloat (*Buffer)[BUFFERSIZE];
ALsizei NumChannels;
ALfloat (*Buffer)[BUFFERSIZE]{nullptr};
ALsizei NumChannels{0};
} MixParams;
typedef struct RealMixParams {
enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
enum Channel ChannelName[MAX_OUTPUT_CHANNELS]{};
ALfloat (*Buffer)[BUFFERSIZE];
ALsizei NumChannels;
ALfloat (*Buffer)[BUFFERSIZE]{nullptr};
ALsizei NumChannels{0};
} RealMixParams;
typedef void (*POSTPROCESS)(ALCdevice *device, ALsizei SamplesToDo);
struct ALCdevice_struct {
RefCount ref;
RefCount ref{0u};
ATOMIC(ALenum) Connected;
enum DeviceType Type;
ATOMIC(ALenum) Connected{AL_TRUE};
DeviceType Type{};
ALuint Frequency;
ALuint UpdateSize;
ALuint NumUpdates;
enum DevFmtChannels FmtChans;
enum DevFmtType FmtType;
ALboolean IsHeadphones;
ALsizei AmbiOrder;
ALuint Frequency{};
ALuint UpdateSize{};
ALuint NumUpdates{};
DevFmtChannels FmtChans{};
DevFmtType FmtType{};
ALboolean IsHeadphones{};
ALsizei AmbiOrder{};
/* For DevFmtAmbi* output only, specifies the channel order and
* normalization.
*/
enum AmbiLayout AmbiLayout;
enum AmbiNorm AmbiScale;
AmbiLayout AmbiLayout{};
AmbiNorm AmbiScale{};
ALCenum LimiterState;
ALCenum LimiterState{ALC_DONT_CARE_SOFT};
char *DeviceName;
char *DeviceName{nullptr};
ATOMIC(ALCenum) LastError;
ATOMIC(ALCenum) LastError{ALC_NO_ERROR};
// Maximum number of sources that can be created
ALuint SourcesMax;
ALuint SourcesMax{};
// Maximum number of slots that can be created
ALuint AuxiliaryEffectSlotMax;
ALuint AuxiliaryEffectSlotMax{};
ALCuint NumMonoSources;
ALCuint NumStereoSources;
ALsizei NumAuxSends;
ALCuint NumMonoSources{};
ALCuint NumStereoSources{};
ALsizei NumAuxSends{};
// Map of Buffers for this device
vector_BufferSubList BufferList;
vector_BufferSubList BufferList{};
almtx_t BufferLock;
// Map of Effects for this device
vector_EffectSubList EffectList;
vector_EffectSubList EffectList{};
almtx_t EffectLock;
// Map of Filters for this device
vector_FilterSubList FilterList;
vector_FilterSubList FilterList{};
almtx_t FilterLock;
POSTPROCESS PostProcess;
POSTPROCESS PostProcess{};
/* HRTF state and info */
struct DirectHrtfState *Hrtf;
char *HrtfName;
struct Hrtf *HrtfHandle;
vector_EnumeratedHrtf HrtfList;
ALCenum HrtfStatus;
struct DirectHrtfState *Hrtf{nullptr};
char *HrtfName{nullptr};
struct Hrtf *HrtfHandle{nullptr};
vector_EnumeratedHrtf HrtfList{};
ALCenum HrtfStatus{ALC_FALSE};
/* UHJ encoder state */
struct Uhj2Encoder *Uhj_Encoder;
struct Uhj2Encoder *Uhj_Encoder{nullptr};
/* High quality Ambisonic decoder */
struct BFormatDec *AmbiDecoder;
struct BFormatDec *AmbiDecoder{nullptr};
/* Stereo-to-binaural filter */
struct bs2b *Bs2b;
struct bs2b *Bs2b{nullptr};
/* First-order ambisonic upsampler for higher-order output */
struct AmbiUpsampler *AmbiUp;
struct AmbiUpsampler *AmbiUp{nullptr};
/* Rendering mode. */
enum RenderMode Render_Mode;
RenderMode Render_Mode{NormalRender};
// Device flags
ALuint Flags;
ALuint Flags{0u};
ALuint64 ClockBase;
ALuint SamplesDone;
ALuint FixedLatency;
ALuint64 ClockBase{0u};
ALuint SamplesDone{0u};
ALuint FixedLatency{0u};
/* Temp storage used for mixer processing. */
alignas(16) ALfloat TempBuffer[4][BUFFERSIZE];
/* The "dry" path corresponds to the main output. */
MixParams Dry;
ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1];
ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1]{};
/* First-order ambisonics output, to be upsampled to the dry buffer if different. */
MixParams FOAOut;
@ -672,36 +664,44 @@ struct ALCdevice_struct {
*/
RealMixParams RealOut;
struct FrontStablizer *Stablizer;
struct FrontStablizer *Stablizer{nullptr};
struct Compressor *Limiter;
struct Compressor *Limiter{nullptr};
/* The average speaker distance as determined by the ambdec configuration
* (or alternatively, by the NFC-HOA reference delay). Only used for NFC.
*/
ALfloat AvgSpeakerDist;
ALfloat AvgSpeakerDist{0.0f};
/* Delay buffers used to compensate for speaker distances. */
DistanceComp ChannelDelay[MAX_OUTPUT_CHANNELS];
/* Dithering control. */
ALfloat DitherDepth;
ALuint DitherSeed;
ALfloat DitherDepth{0.0f};
ALuint DitherSeed{0u};
/* Running count of the mixer invocations, in 31.1 fixed point. This
* actually increments *twice* when mixing, first at the start and then at
* the end, so the bottom bit indicates if the device is currently mixing
* and the upper bits indicates how many mixes have been done.
*/
RefCount MixCount;
RefCount MixCount{0u};
// Contexts created on this device
ATOMIC(ALCcontext*) ContextList;
ATOMIC(ALCcontext*) ContextList{nullptr};
almtx_t BackendLock;
struct ALCbackend *Backend;
struct ALCbackend *Backend{nullptr};
ATOMIC(ALCdevice*) next;
ATOMIC(ALCdevice*) next{nullptr};
ALCdevice_struct(DeviceType type);
ALCdevice_struct(const ALCdevice_struct&) = delete;
ALCdevice_struct& operator=(const ALCdevice_struct&) = delete;
~ALCdevice_struct();
DEF_NEWDEL(ALCdevice)
};
// Frequency was requested by the app or config file
@ -807,10 +807,7 @@ int EventThread(void *arg);
char *alstrdup(const char *str);
#ifdef __cplusplus
} // extern "C"
std::vector<std::string> SearchDataFiles(const char *match, const char *subdir);
#endif
#endif