Skip to content

Commit

Permalink
Merge branch 'ddnet' into chillerbot
Browse files Browse the repository at this point in the history
  • Loading branch information
ChillerDragon committed Dec 27, 2024
2 parents ae8f584 + 81db700 commit 5eab4c7
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 73 deletions.
3 changes: 3 additions & 0 deletions src/engine/client/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ CGraph::CGraph(int MaxEntries) :

void CGraph::Init(float Min, float Max)
{
m_Entries.Clear();
m_pFirstScaled = nullptr;
m_RenderedTotalTime = 0;
SetMin(Min);
SetMax(Max);
}
Expand Down
121 changes: 65 additions & 56 deletions src/engine/client/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ int CSound::Init()

// Initialize sample indices. We always need them to load sounds in
// the editor even if sound is disabled or failed to be enabled.
const CLockScope LockScope(m_SoundLock);
m_FirstFreeSampleIndex = 0;
for(size_t i = 0; i < std::size(m_aSamples) - 1; ++i)
{
Expand Down Expand Up @@ -235,10 +236,10 @@ int CSound::Init()
#endif
m_pMixBuffer = (int *)calloc(m_MaxFrames * 2, sizeof(int));

SDL_PauseAudioDevice(m_Device, 0);

m_SoundEnabled = true;
Update();

SDL_PauseAudioDevice(m_Device, 0);
return 0;
}

Expand All @@ -258,19 +259,28 @@ void CSound::UpdateVolume()

void CSound::Shutdown()
{
for(unsigned SampleId = 0; SampleId < NUM_SAMPLES; SampleId++)
{
UnloadSample(SampleId);
}
StopAll();

// Stop sound callback before freeing sample data
SDL_CloseAudioDevice(m_Device);
SDL_QuitSubSystem(SDL_INIT_AUDIO);
m_Device = 0;

const CLockScope LockScope(m_SoundLock);
for(auto &Sample : m_aSamples)
{
free(Sample.m_pData);
Sample.m_pData = nullptr;
}

free(m_pMixBuffer);
m_pMixBuffer = nullptr;
m_SoundEnabled = false;
}

CSample *CSound::AllocSample()
{
const CLockScope LockScope(m_SoundLock);
if(m_FirstFreeSampleIndex == SAMPLE_INDEX_FULL)
return nullptr;

Expand All @@ -289,7 +299,7 @@ CSample *CSound::AllocSample()

void CSound::RateConvert(CSample &Sample) const
{
dbg_assert(Sample.m_pData != nullptr, "Sample is not loaded");
dbg_assert(Sample.IsLoaded(), "Sample not loaded");
// make sure that we need to convert this sound
if(Sample.m_Rate == m_MixingRate)
return;
Expand Down Expand Up @@ -514,9 +524,6 @@ int CSound::LoadOpus(const char *pFilename, int StorageType)
if(!m_SoundEnabled)
return -1;

if(!m_pStorage)
return -1;

CSample *pSample = AllocSample();
if(!pSample)
{
Expand Down Expand Up @@ -554,9 +561,6 @@ int CSound::LoadWV(const char *pFilename, int StorageType)
if(!m_SoundEnabled)
return -1;

if(!m_pStorage)
return -1;

CSample *pSample = AllocSample();
if(!pSample)
{
Expand Down Expand Up @@ -588,13 +592,10 @@ int CSound::LoadWV(const char *pFilename, int StorageType)
return pSample->m_Index;
}

int CSound::LoadOpusFromMem(const void *pData, unsigned DataSize, bool FromEditor = false)
int CSound::LoadOpusFromMem(const void *pData, unsigned DataSize, bool ForceLoad = false)
{
// no need to load sound when we are running with no sound
if(!m_SoundEnabled && !FromEditor)
return -1;

if(!pData)
if(!m_SoundEnabled && !ForceLoad)
return -1;

CSample *pSample = AllocSample();
Expand All @@ -611,13 +612,10 @@ int CSound::LoadOpusFromMem(const void *pData, unsigned DataSize, bool FromEdito
return pSample->m_Index;
}

int CSound::LoadWVFromMem(const void *pData, unsigned DataSize, bool FromEditor = false)
int CSound::LoadWVFromMem(const void *pData, unsigned DataSize, bool ForceLoad = false)
{
// no need to load sound when we are running with no sound
if(!m_SoundEnabled && !FromEditor)
return -1;

if(!pData)
if(!m_SoundEnabled && !ForceLoad)
return -1;

CSample *pSample = AllocSample();
Expand All @@ -636,12 +634,13 @@ int CSound::LoadWVFromMem(const void *pData, unsigned DataSize, bool FromEditor

void CSound::UnloadSample(int SampleId)
{
if(SampleId == -1 || SampleId >= NUM_SAMPLES)
if(SampleId == -1)
return;

Stop(SampleId);

// Free data
const CLockScope LockScope(m_SoundLock);
CSample &Sample = m_aSamples[SampleId];
free(Sample.m_pData);
Sample.m_pData = nullptr;
Expand All @@ -656,18 +655,19 @@ void CSound::UnloadSample(int SampleId)

float CSound::GetSampleTotalTime(int SampleId)
{
if(SampleId == -1 || SampleId >= NUM_SAMPLES)
return 0.0f;
dbg_assert(SampleId >= 0 && SampleId < NUM_SAMPLES, "SampleId invalid");

const CLockScope LockScope(m_SoundLock);
dbg_assert(m_aSamples[SampleId].IsLoaded(), "Sample not loaded");
return m_aSamples[SampleId].TotalTime();
}

float CSound::GetSampleCurrentTime(int SampleId)
{
if(SampleId == -1 || SampleId >= NUM_SAMPLES)
return 0.0f;
dbg_assert(SampleId >= 0 && SampleId < NUM_SAMPLES, "SampleId invalid");

const CLockScope LockScope(m_SoundLock);
dbg_assert(m_aSamples[SampleId].IsLoaded(), "Sample not loaded");
CSample *pSample = &m_aSamples[SampleId];
for(auto &Voice : m_aVoices)
{
Expand All @@ -682,10 +682,10 @@ float CSound::GetSampleCurrentTime(int SampleId)

void CSound::SetSampleCurrentTime(int SampleId, float Time)
{
if(SampleId == -1 || SampleId >= NUM_SAMPLES)
return;
dbg_assert(SampleId >= 0 && SampleId < NUM_SAMPLES, "SampleId invalid");

const CLockScope LockScope(m_SoundLock);
dbg_assert(m_aSamples[SampleId].IsLoaded(), "Sample not loaded");
CSample *pSample = &m_aSamples[SampleId];
for(auto &Voice : m_aVoices)
{
Expand All @@ -701,6 +701,9 @@ void CSound::SetSampleCurrentTime(int SampleId, float Time)

void CSound::SetChannel(int ChannelId, float Vol, float Pan)
{
dbg_assert(ChannelId >= 0 && ChannelId < NUM_CHANNELS, "ChannelId invalid");

const CLockScope LockScope(m_SoundLock);
m_aChannels[ChannelId].m_Vol = (int)(Vol * 255.0f);
m_aChannels[ChannelId].m_Pan = (int)(Pan * 255.0f); // TODO: this is only on and off right now
}
Expand Down Expand Up @@ -836,36 +839,34 @@ ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, float
break;
}
}
if(VoiceId == -1)
{
return CreateVoiceHandle(-1, -1);
}

// voice found, use it
int Age = -1;
if(VoiceId != -1)
m_aVoices[VoiceId].m_pSample = &m_aSamples[SampleId];
m_aVoices[VoiceId].m_pChannel = &m_aChannels[ChannelId];
if(Flags & FLAG_LOOP)
{
m_aVoices[VoiceId].m_pSample = &m_aSamples[SampleId];
m_aVoices[VoiceId].m_pChannel = &m_aChannels[ChannelId];
if(Flags & FLAG_LOOP)
{
m_aVoices[VoiceId].m_Tick = m_aSamples[SampleId].m_PausedAt;
}
else if(Flags & FLAG_PREVIEW)
{
m_aVoices[VoiceId].m_Tick = m_aSamples[SampleId].m_PausedAt;
m_aSamples[SampleId].m_PausedAt = 0;
}
else
{
m_aVoices[VoiceId].m_Tick = 0;
}
m_aVoices[VoiceId].m_Vol = (int)(clamp(Volume, 0.0f, 1.0f) * 255.0f);
m_aVoices[VoiceId].m_Flags = Flags;
m_aVoices[VoiceId].m_Position = Position;
m_aVoices[VoiceId].m_Falloff = 0.0f;
m_aVoices[VoiceId].m_Shape = ISound::SHAPE_CIRCLE;
m_aVoices[VoiceId].m_Circle.m_Radius = 1500;
Age = m_aVoices[VoiceId].m_Age;
m_aVoices[VoiceId].m_Tick = m_aSamples[SampleId].m_PausedAt;
}

return CreateVoiceHandle(VoiceId, Age);
else if(Flags & FLAG_PREVIEW)
{
m_aVoices[VoiceId].m_Tick = m_aSamples[SampleId].m_PausedAt;
m_aSamples[SampleId].m_PausedAt = 0;
}
else
{
m_aVoices[VoiceId].m_Tick = 0;
}
m_aVoices[VoiceId].m_Vol = (int)(clamp(Volume, 0.0f, 1.0f) * 255.0f);
m_aVoices[VoiceId].m_Flags = Flags;
m_aVoices[VoiceId].m_Position = Position;
m_aVoices[VoiceId].m_Falloff = 0.0f;
m_aVoices[VoiceId].m_Shape = ISound::SHAPE_CIRCLE;
m_aVoices[VoiceId].m_Circle.m_Radius = 1500;
return CreateVoiceHandle(VoiceId, m_aVoices[VoiceId].m_Age);
}

ISound::CVoiceHandle CSound::PlayAt(int ChannelId, int SampleId, int Flags, float Volume, vec2 Position)
Expand All @@ -880,9 +881,12 @@ ISound::CVoiceHandle CSound::Play(int ChannelId, int SampleId, int Flags, float

void CSound::Pause(int SampleId)
{
dbg_assert(SampleId >= 0 && SampleId < NUM_SAMPLES, "SampleId invalid");

// TODO: a nice fade out
const CLockScope LockScope(m_SoundLock);
CSample *pSample = &m_aSamples[SampleId];
dbg_assert(m_aSamples[SampleId].IsLoaded(), "Sample not loaded");
for(auto &Voice : m_aVoices)
{
if(Voice.m_pSample == pSample)
Expand All @@ -895,9 +899,12 @@ void CSound::Pause(int SampleId)

void CSound::Stop(int SampleId)
{
dbg_assert(SampleId >= 0 && SampleId < NUM_SAMPLES, "SampleId invalid");

// TODO: a nice fade out
const CLockScope LockScope(m_SoundLock);
CSample *pSample = &m_aSamples[SampleId];
dbg_assert(m_aSamples[SampleId].IsLoaded(), "Sample not loaded");
for(auto &Voice : m_aVoices)
{
if(Voice.m_pSample == pSample)
Expand Down Expand Up @@ -945,8 +952,10 @@ void CSound::StopVoice(CVoiceHandle Voice)

bool CSound::IsPlaying(int SampleId)
{
dbg_assert(SampleId >= 0 && SampleId < NUM_SAMPLES, "SampleId invalid");
const CLockScope LockScope(m_SoundLock);
const CSample *pSample = &m_aSamples[SampleId];
dbg_assert(m_aSamples[SampleId].IsLoaded(), "Sample not loaded");
return std::any_of(std::begin(m_aVoices), std::end(m_aVoices), [pSample](const auto &Voice) { return Voice.m_pSample == pSample; });
}

Expand Down
27 changes: 16 additions & 11 deletions src/engine/client/sound.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ struct CSample
{
return m_NumFrames / (float)m_Rate;
}

bool IsLoaded() const
{
return m_pData != nullptr;
}
};

struct CChannel
Expand Down Expand Up @@ -68,12 +73,12 @@ class CSound : public IEngineSound
SDL_AudioDeviceID m_Device = 0;
CLock m_SoundLock;

CSample m_aSamples[NUM_SAMPLES] = {{0}};
int m_FirstFreeSampleIndex = 0;
CSample m_aSamples[NUM_SAMPLES] GUARDED_BY(m_SoundLock) = {{0}};
int m_FirstFreeSampleIndex GUARDED_BY(m_SoundLock) = 0;

CVoice m_aVoices[NUM_VOICES] = {{0}};
CChannel m_aChannels[NUM_CHANNELS] = {{255, 0}};
int m_NextVoice = 0;
CVoice m_aVoices[NUM_VOICES] GUARDED_BY(m_SoundLock) = {{0}};
CChannel m_aChannels[NUM_CHANNELS] GUARDED_BY(m_SoundLock) = {{255, 0}};
int m_NextVoice GUARDED_BY(m_SoundLock) = 0;
uint32_t m_MaxFrames = 0;

// This is not an std::atomic<vec2> as this would require linking with
Expand All @@ -88,7 +93,7 @@ class CSound : public IEngineSound

int *m_pMixBuffer = nullptr;

CSample *AllocSample();
CSample *AllocSample() REQUIRES(!m_SoundLock);
void RateConvert(CSample &Sample) const;

bool DecodeOpus(CSample &Sample, const void *pData, unsigned DataSize) const;
Expand All @@ -97,23 +102,23 @@ class CSound : public IEngineSound
void UpdateVolume();

public:
int Init() override;
int Init() override REQUIRES(!m_SoundLock);
int Update() override;
void Shutdown() override REQUIRES(!m_SoundLock);

bool IsSoundEnabled() override { return m_SoundEnabled; }

int LoadOpus(const char *pFilename, int StorageType = IStorage::TYPE_ALL) override REQUIRES(!m_SoundLock);
int LoadWV(const char *pFilename, int StorageType = IStorage::TYPE_ALL) override REQUIRES(!m_SoundLock);
int LoadOpusFromMem(const void *pData, unsigned DataSize, bool FromEditor) override REQUIRES(!m_SoundLock);
int LoadWVFromMem(const void *pData, unsigned DataSize, bool FromEditor) override REQUIRES(!m_SoundLock);
int LoadOpusFromMem(const void *pData, unsigned DataSize, bool ForceLoad) override REQUIRES(!m_SoundLock);
int LoadWVFromMem(const void *pData, unsigned DataSize, bool ForceLoad) override REQUIRES(!m_SoundLock);
void UnloadSample(int SampleId) override REQUIRES(!m_SoundLock);

float GetSampleTotalTime(int SampleId) override; // in s
float GetSampleTotalTime(int SampleId) override REQUIRES(!m_SoundLock); // in s
float GetSampleCurrentTime(int SampleId) override REQUIRES(!m_SoundLock); // in s
void SetSampleCurrentTime(int SampleId, float Time) override REQUIRES(!m_SoundLock);

void SetChannel(int ChannelId, float Vol, float Pan) override;
void SetChannel(int ChannelId, float Vol, float Pan) override REQUIRES(!m_SoundLock);
void SetListenerPosition(vec2 Position) override;

void SetVoiceVolume(CVoiceHandle Voice, float Volume) override REQUIRES(!m_SoundLock);
Expand Down
12 changes: 9 additions & 3 deletions src/engine/shared/ringbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,22 @@ CRingBufferBase::CItem *CRingBufferBase::MergeBack(CItem *pItem)

void CRingBufferBase::Init(void *pMemory, int Size, int Flags)
{
m_Size = (Size) / sizeof(CItem) * sizeof(CItem);
m_pFirst = (CItem *)pMemory;
m_Size = Size / sizeof(CItem) * sizeof(CItem);
m_pBuffer = static_cast<CItem *>(pMemory);
m_Flags = Flags;
Clear();
}

void CRingBufferBase::Clear()
{
m_pFirst = m_pBuffer;
m_pFirst->m_pPrev = nullptr;
m_pFirst->m_pNext = nullptr;
m_pFirst->m_Free = 1;
m_pFirst->m_Size = m_Size;
m_pLast = m_pFirst;
m_pProduce = m_pFirst;
m_pConsume = m_pFirst;
m_Flags = Flags;
}

void *CRingBufferBase::Allocate(int Size)
Expand Down
4 changes: 4 additions & 0 deletions src/engine/shared/ringbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class CRingBufferBase
int m_Size;
};

CItem *m_pBuffer;

CItem *m_pProduce;
CItem *m_pConsume;

Expand Down Expand Up @@ -52,6 +54,8 @@ class CRingBufferBase
FLAG_RECYCLE = 1
};
static constexpr int ITEM_SIZE = sizeof(CItem);

void Clear();
};

template<typename T>
Expand Down
Loading

0 comments on commit 5eab4c7

Please sign in to comment.