mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-23 14:53:52 +00:00
Preprocess audio into S16 for faster mixing.
This commit is contained in:
@@ -58,33 +58,41 @@ static void AlignedFree(void *ptr)
|
|||||||
class GpAudioBuffer_SDL2 final : public IGpAudioBuffer
|
class GpAudioBuffer_SDL2 final : public IGpAudioBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef int16_t AudioSample_t;
|
||||||
|
|
||||||
static GpAudioBuffer_SDL2 *Create(const void *data, size_t size);
|
static GpAudioBuffer_SDL2 *Create(const void *data, size_t size);
|
||||||
|
|
||||||
void AddRef() override;
|
void AddRef() override;
|
||||||
void Release() override;
|
void Release() override;
|
||||||
|
|
||||||
const void *GetData() const;
|
const AudioSample_t *GetData() const;
|
||||||
size_t GetSize() const;
|
size_t GetSize() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GpAudioBuffer_SDL2(const void *data, size_t size);
|
GpAudioBuffer_SDL2(const AudioSample_t *data, size_t size);
|
||||||
~GpAudioBuffer_SDL2();
|
~GpAudioBuffer_SDL2();
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
const void *m_data;
|
const AudioSample_t *m_data;
|
||||||
size_t m_size;
|
size_t m_size;
|
||||||
SDL_atomic_t m_count;
|
SDL_atomic_t m_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
GpAudioBuffer_SDL2 *GpAudioBuffer_SDL2::Create(const void *data, size_t size)
|
GpAudioBuffer_SDL2 *GpAudioBuffer_SDL2::Create(const void *data, size_t size)
|
||||||
{
|
{
|
||||||
void *storage = malloc(size + sizeof(GpAudioBuffer_SDL2));
|
size_t baseSize = sizeof(GpAudioBuffer_SDL2) + GP_SYSTEM_MEMORY_ALIGNMENT + 1;
|
||||||
|
baseSize -= baseSize % GP_SYSTEM_MEMORY_ALIGNMENT;
|
||||||
|
void *storage = malloc(size * sizeof(AudioSample_t) + baseSize);
|
||||||
if (!storage)
|
if (!storage)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
void *dataPos = static_cast<uint8_t*>(storage) + sizeof(GpAudioBuffer_SDL2);
|
AudioSample_t *dataPos = reinterpret_cast<AudioSample_t*>(static_cast<uint8_t*>(storage) + baseSize);
|
||||||
memcpy(dataPos, data, size);
|
|
||||||
|
// Convert from u8 to s16
|
||||||
|
const uint8_t *srcData = static_cast<const uint8_t*>(data);
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
dataPos[i] = srcData[i] - 0x80;
|
||||||
|
|
||||||
return new (storage) GpAudioBuffer_SDL2(dataPos, size);
|
return new (storage) GpAudioBuffer_SDL2(dataPos, size);
|
||||||
}
|
}
|
||||||
@@ -102,7 +110,7 @@ void GpAudioBuffer_SDL2::Release()
|
|||||||
this->Destroy();
|
this->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
const void *GpAudioBuffer_SDL2::GetData() const
|
const int16_t *GpAudioBuffer_SDL2::GetData() const
|
||||||
{
|
{
|
||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
@@ -113,7 +121,7 @@ size_t GpAudioBuffer_SDL2::GetSize() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GpAudioBuffer_SDL2::GpAudioBuffer_SDL2(const void *data, size_t size)
|
GpAudioBuffer_SDL2::GpAudioBuffer_SDL2(const int16_t *data, size_t size)
|
||||||
: m_data(data)
|
: m_data(data)
|
||||||
, m_size(size)
|
, m_size(size)
|
||||||
{
|
{
|
||||||
@@ -135,6 +143,7 @@ class GpAudioChannel_SDL2 final : public IGpAudioChannel
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
friend class GpAudioDriver_SDL2;
|
friend class GpAudioDriver_SDL2;
|
||||||
|
typedef GpAudioBuffer_SDL2::AudioSample_t AudioSample_t;
|
||||||
|
|
||||||
GpAudioChannel_SDL2(GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate);
|
GpAudioChannel_SDL2(GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate);
|
||||||
~GpAudioChannel_SDL2();
|
~GpAudioChannel_SDL2();
|
||||||
@@ -147,7 +156,7 @@ public:
|
|||||||
void Stop() override;
|
void Stop() override;
|
||||||
void Destroy() override;
|
void Destroy() override;
|
||||||
|
|
||||||
void Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime);
|
void Consume(int16_t *output, size_t sz, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime);
|
||||||
|
|
||||||
static GpAudioChannel_SDL2 *Alloc(GpAudioDriver_SDL2 *driver, GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate);
|
static GpAudioChannel_SDL2 *Alloc(GpAudioDriver_SDL2 *driver, GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate);
|
||||||
|
|
||||||
@@ -183,6 +192,9 @@ class GpAudioDriver_SDL2 final : public IGpAudioDriver, public IGpPrefsHandler
|
|||||||
public:
|
public:
|
||||||
friend class GpAudioChannel_SDL2;
|
friend class GpAudioChannel_SDL2;
|
||||||
|
|
||||||
|
typedef GpAudioChannel_SDL2::AudioSample_t AudioSample_t;
|
||||||
|
|
||||||
|
|
||||||
explicit GpAudioDriver_SDL2(const GpAudioDriverProperties &properties);
|
explicit GpAudioDriver_SDL2(const GpAudioDriverProperties &properties);
|
||||||
~GpAudioDriver_SDL2();
|
~GpAudioDriver_SDL2();
|
||||||
|
|
||||||
@@ -206,13 +218,14 @@ private:
|
|||||||
|
|
||||||
void MixAudio(void *stream, size_t len);
|
void MixAudio(void *stream, size_t len);
|
||||||
void RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels, size_t maxSamplesToFill, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime);
|
void RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels, size_t maxSamplesToFill, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime);
|
||||||
|
static void AddSamples(AudioSample_t *GP_RESTRICT dest, const AudioSample_t *GP_RESTRICT src, size_t nSamples);
|
||||||
|
|
||||||
GpAudioDriverProperties m_properties;
|
GpAudioDriverProperties m_properties;
|
||||||
IGpMutex *m_mutex;
|
IGpMutex *m_mutex;
|
||||||
IGpMutex *m_mixState;
|
IGpMutex *m_mixState;
|
||||||
|
|
||||||
static const size_t kMaxChannels = 16;
|
static const size_t kMaxChannels = 16;
|
||||||
static const size_t kMixChunkSize = 512;
|
static const size_t kMixChunkSamples = 512;
|
||||||
static const int16_t kMaxAudioVolumeScale = 64;
|
static const int16_t kMaxAudioVolumeScale = 64;
|
||||||
|
|
||||||
GpAudioChannel_SDL2 *m_channels[kMaxChannels];
|
GpAudioChannel_SDL2 *m_channels[kMaxChannels];
|
||||||
@@ -225,7 +238,7 @@ private:
|
|||||||
|
|
||||||
bool m_sdlAudioRunning;
|
bool m_sdlAudioRunning;
|
||||||
|
|
||||||
GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) int16_t m_mixChunk[kMixChunkSize];
|
GP_ALIGNED(GP_SYSTEM_MEMORY_ALIGNMENT) int16_t m_mixChunk[kMixChunkSamples];
|
||||||
size_t m_mixChunkReadOffset;
|
size_t m_mixChunkReadOffset;
|
||||||
|
|
||||||
int16_t m_audioVolumeScale;
|
int16_t m_audioVolumeScale;
|
||||||
@@ -370,7 +383,7 @@ bool GpAudioChannel_SDL2::Init(GpAudioDriver_SDL2 *driver)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime)
|
void GpAudioChannel_SDL2::Consume(int16_t *output, size_t sz, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime)
|
||||||
{
|
{
|
||||||
m_mutex->Lock();
|
m_mutex->Lock();
|
||||||
|
|
||||||
@@ -380,7 +393,7 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2
|
|||||||
|
|
||||||
if (sz <= m_leadingSilence)
|
if (sz <= m_leadingSilence)
|
||||||
{
|
{
|
||||||
memset(output, 0x80, sz);
|
memset(output, 0, sz * sizeof(AudioSample_t));
|
||||||
m_leadingSilence -= sz;
|
m_leadingSilence -= sz;
|
||||||
|
|
||||||
m_isMixing = false;
|
m_isMixing = false;
|
||||||
@@ -392,7 +405,7 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2
|
|||||||
size_t leadingSilence = m_leadingSilence;
|
size_t leadingSilence = m_leadingSilence;
|
||||||
if (leadingSilence > 0)
|
if (leadingSilence > 0)
|
||||||
{
|
{
|
||||||
memset(output, 0x80, leadingSilence);
|
memset(output, 0, leadingSilence * sizeof(AudioSample_t));
|
||||||
output += leadingSilence;
|
output += leadingSilence;
|
||||||
sz -= leadingSilence;
|
sz -= leadingSilence;
|
||||||
|
|
||||||
@@ -403,7 +416,7 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2
|
|||||||
while (m_numQueuedBuffers > 0)
|
while (m_numQueuedBuffers > 0)
|
||||||
{
|
{
|
||||||
GpAudioBuffer_SDL2 *buffer = m_pendingBuffers[m_nextPendingBufferConsumePos];
|
GpAudioBuffer_SDL2 *buffer = m_pendingBuffers[m_nextPendingBufferConsumePos];
|
||||||
const void *bufferData = buffer->GetData();
|
const int16_t *bufferData = buffer->GetData();
|
||||||
const size_t bufferSize = buffer->GetSize();
|
const size_t bufferSize = buffer->GetSize();
|
||||||
|
|
||||||
assert(m_firstBufferSamplesConsumed < bufferSize);
|
assert(m_firstBufferSamplesConsumed < bufferSize);
|
||||||
@@ -411,7 +424,7 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2
|
|||||||
const size_t available = (bufferSize - m_firstBufferSamplesConsumed);
|
const size_t available = (bufferSize - m_firstBufferSamplesConsumed);
|
||||||
if (available <= sz)
|
if (available <= sz)
|
||||||
{
|
{
|
||||||
memcpy(output, static_cast<const uint8_t*>(bufferData) + m_firstBufferSamplesConsumed, available);
|
memcpy(output, bufferData + m_firstBufferSamplesConsumed, available * sizeof(AudioSample_t));
|
||||||
sz -= available;
|
sz -= available;
|
||||||
output += available;
|
output += available;
|
||||||
|
|
||||||
@@ -430,7 +443,7 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(output, static_cast<const uint8_t*>(bufferData) + m_firstBufferSamplesConsumed, sz);
|
memcpy(output, bufferData + m_firstBufferSamplesConsumed, sz * sizeof(AudioSample_t));
|
||||||
m_firstBufferSamplesConsumed += sz;
|
m_firstBufferSamplesConsumed += sz;
|
||||||
output += sz;
|
output += sz;
|
||||||
sz = 0;
|
sz = 0;
|
||||||
@@ -442,7 +455,7 @@ void GpAudioChannel_SDL2::Consume(uint8_t *output, size_t sz, GpAudioDriver_SDL2
|
|||||||
|
|
||||||
m_mutex->Unlock();
|
m_mutex->Unlock();
|
||||||
|
|
||||||
memset(output, 0x80, sz);
|
memset(output, 0, sz * sizeof(AudioSample_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
GpAudioChannel_SDL2 *GpAudioChannel_SDL2::Alloc(GpAudioDriver_SDL2 *driver, GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate)
|
GpAudioChannel_SDL2 *GpAudioChannel_SDL2::Alloc(GpAudioDriver_SDL2 *driver, GpAudioDriver_SDL2_Duration_t latency, GpAudioDriver_SDL2_Duration_t bufferTime, size_t bufferSamplesMax, uint16_t sampleRate)
|
||||||
@@ -473,14 +486,14 @@ GpAudioDriver_SDL2::GpAudioDriver_SDL2(const GpAudioDriverProperties &properties
|
|||||||
, m_latency(GpAudioDriver_SDL2_Duration_t::zero())
|
, m_latency(GpAudioDriver_SDL2_Duration_t::zero())
|
||||||
, m_bufferTime(GpAudioDriver_SDL2_Duration_t::zero())
|
, m_bufferTime(GpAudioDriver_SDL2_Duration_t::zero())
|
||||||
, m_sdlAudioRunning(false)
|
, m_sdlAudioRunning(false)
|
||||||
, m_mixChunkReadOffset(kMixChunkSize)
|
, m_mixChunkReadOffset(kMixChunkSamples)
|
||||||
, m_audioVolumeScale(kMaxAudioVolumeScale)
|
, m_audioVolumeScale(kMaxAudioVolumeScale)
|
||||||
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < kMaxChannels; i++)
|
for (size_t i = 0; i < kMaxChannels; i++)
|
||||||
m_channels[i] = nullptr;
|
m_channels[i] = nullptr;
|
||||||
|
|
||||||
for (size_t i = 0; i < kMixChunkSize; i++)
|
for (size_t i = 0; i < kMixChunkSamples; i++)
|
||||||
m_mixChunk[i] = 0;
|
m_mixChunk[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,7 +573,7 @@ bool GpAudioDriver_SDL2::Init()
|
|||||||
requestedSpec.channels = 1;
|
requestedSpec.channels = 1;
|
||||||
requestedSpec.format = AUDIO_S16;
|
requestedSpec.format = AUDIO_S16;
|
||||||
requestedSpec.freq = m_properties.m_sampleRate;
|
requestedSpec.freq = m_properties.m_sampleRate;
|
||||||
requestedSpec.samples = kMixChunkSize;
|
requestedSpec.samples = kMixChunkSamples;
|
||||||
requestedSpec.userdata = this;
|
requestedSpec.userdata = this;
|
||||||
|
|
||||||
if (SDL_OpenAudio(&requestedSpec, nullptr))
|
if (SDL_OpenAudio(&requestedSpec, nullptr))
|
||||||
@@ -628,7 +641,7 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len)
|
|||||||
size_t samplesSinceStart = 0;
|
size_t samplesSinceStart = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
size_t availableInMixChunk = kMixChunkSize - m_mixChunkReadOffset;
|
size_t availableInMixChunk = kMixChunkSamples - m_mixChunkReadOffset;
|
||||||
|
|
||||||
if (availableInMixChunk > samplesRemaining)
|
if (availableInMixChunk > samplesRemaining)
|
||||||
{
|
{
|
||||||
@@ -662,20 +675,21 @@ void GpAudioDriver_SDL2::MixAudio(void *stream, size_t len)
|
|||||||
|
|
||||||
void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels, size_t maxSamplesToFill, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime)
|
void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, size_t numChannels, size_t maxSamplesToFill, GpAudioDriver_SDL2_TimePoint_t mixStartTime, GpAudioDriver_SDL2_TimePoint_t mixEndTime)
|
||||||
{
|
{
|
||||||
uint8_t audioMixBufferUnaligned[kMixChunkSize + GP_SYSTEM_MEMORY_ALIGNMENT];
|
uint8_t audioMixBufferUnaligned[kMixChunkSamples * sizeof(AudioSample_t) + GP_SYSTEM_MEMORY_ALIGNMENT];
|
||||||
uint8_t *audioMixBuffer = audioMixBufferUnaligned;
|
uint8_t *audioMixBufferBytes = audioMixBufferUnaligned;
|
||||||
|
|
||||||
{
|
{
|
||||||
uintptr_t bufferPtr = reinterpret_cast<uintptr_t>(audioMixBuffer);
|
uintptr_t bufferPtr = reinterpret_cast<uintptr_t>(audioMixBufferBytes);
|
||||||
size_t alignPadding = GP_SYSTEM_MEMORY_ALIGNMENT - (bufferPtr % GP_SYSTEM_MEMORY_ALIGNMENT);
|
size_t alignPadding = GP_SYSTEM_MEMORY_ALIGNMENT - (bufferPtr % GP_SYSTEM_MEMORY_ALIGNMENT);
|
||||||
audioMixBuffer += alignPadding;
|
audioMixBufferBytes += alignPadding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioSample_t *audioMixBuffer = reinterpret_cast<AudioSample_t*>(audioMixBufferBytes);
|
||||||
bool noAudio = true;
|
bool noAudio = true;
|
||||||
|
|
||||||
const int16_t audioVolumeScale = m_audioVolumeScale;
|
const int16_t audioVolumeScale = m_audioVolumeScale;
|
||||||
|
|
||||||
size_t samplesToFill = kMixChunkSize;
|
size_t samplesToFill = kMixChunkSamples;
|
||||||
if (samplesToFill > maxSamplesToFill)
|
if (samplesToFill > maxSamplesToFill)
|
||||||
{
|
{
|
||||||
m_mixChunkReadOffset += samplesToFill - maxSamplesToFill;
|
m_mixChunkReadOffset += samplesToFill - maxSamplesToFill;
|
||||||
@@ -684,8 +698,7 @@ void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, siz
|
|||||||
else
|
else
|
||||||
m_mixChunkReadOffset = 0;
|
m_mixChunkReadOffset = 0;
|
||||||
|
|
||||||
int16_t *mixChunkStart = m_mixChunk + m_mixChunkReadOffset;
|
AudioSample_t *mixChunkStart = m_mixChunk + m_mixChunkReadOffset;
|
||||||
int16_t audioNormalizeShift = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < numChannels; i++)
|
for (size_t i = 0; i < numChannels; i++)
|
||||||
{
|
{
|
||||||
@@ -694,27 +707,27 @@ void GpAudioDriver_SDL2::RefillMixChunk(GpAudioChannel_SDL2 *const*channels, siz
|
|||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
noAudio = false;
|
noAudio = false;
|
||||||
audioNormalizeShift = 0x80;
|
memcpy(mixChunkStart, audioMixBuffer, samplesToFill * sizeof(AudioSample_t));
|
||||||
for (size_t j = 0; j < samplesToFill; j++)
|
|
||||||
mixChunkStart[j] = static_cast<int16_t>(audioMixBuffer[j]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
AddSamples(mixChunkStart, audioMixBuffer, samplesToFill);
|
||||||
audioNormalizeShift += 0x80;
|
|
||||||
for (size_t j = 0; j < samplesToFill; j++)
|
|
||||||
mixChunkStart[j] += static_cast<int16_t>(audioMixBuffer[j]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noAudio)
|
if (noAudio)
|
||||||
memset(mixChunkStart, 0, samplesToFill * sizeof(mixChunkStart[0]));
|
memset(mixChunkStart, 0, samplesToFill * sizeof(AudioSample_t));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < samplesToFill; i++)
|
for (size_t i = 0; i < samplesToFill; i++)
|
||||||
mixChunkStart[i] = (mixChunkStart[i] - audioNormalizeShift) * audioVolumeScale;
|
mixChunkStart[i] *= audioVolumeScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GpAudioDriver_SDL2::AddSamples(AudioSample_t *GP_RESTRICT dest, const AudioSample_t *GP_RESTRICT src, size_t nSamples)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < nSamples; i++)
|
||||||
|
dest[i] += src[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GpAudioDriver_SDL2_TimePoint_t GpAudioDriver_SDL2::GetCurrentTime()
|
GpAudioDriver_SDL2_TimePoint_t GpAudioDriver_SDL2::GetCurrentTime()
|
||||||
{
|
{
|
||||||
|
@@ -13,11 +13,13 @@
|
|||||||
#define GP_ALIGNED(n) __declspec(align(n))
|
#define GP_ALIGNED(n) __declspec(align(n))
|
||||||
#else
|
#else
|
||||||
#define GP_ALIGNED(n) __attribute__((aligned(n)))
|
#define GP_ALIGNED(n) __attribute__((aligned(n)))
|
||||||
|
#define GP_RESTRICT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GP_IS_CPP11
|
#if GP_IS_CPP11
|
||||||
#define GP_DELETED = delete
|
#define GP_DELETED = delete
|
||||||
#define GP_STATIC_ASSERT(n) static_assert((n), "Static assert failed: " #n)
|
#define GP_STATIC_ASSERT(n) static_assert((n), "Static assert failed: " #n)
|
||||||
|
#define GP_RESTRICT __restrict
|
||||||
#else
|
#else
|
||||||
#ifndef nullptr
|
#ifndef nullptr
|
||||||
#define nullptr 0
|
#define nullptr 0
|
||||||
@@ -32,6 +34,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define GP_DELETED
|
#define GP_DELETED
|
||||||
|
#define GP_RESTRICT
|
||||||
|
|
||||||
template<bool TCondition>
|
template<bool TCondition>
|
||||||
struct __GpStaticAssertHelper
|
struct __GpStaticAssertHelper
|
||||||
|
Reference in New Issue
Block a user