mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-13 11:38:19 +00:00
7ae4b39574
- videorecorder only works for recording demos now - demoplayer was modified to allow controll over the time that passed in order to get perfect fps, IVideo controlls how much time passed, basically every rendercall sets the time to record the next frame
233 lines
5.3 KiB
C++
233 lines
5.3 KiB
C++
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
|
|
#include <base/tl/array.h>
|
|
|
|
#include <engine/engine.h>
|
|
#include <engine/sound.h>
|
|
#include <engine/shared/config.h>
|
|
#include <game/generated/client_data.h>
|
|
#include <game/client/gameclient.h>
|
|
#include <game/client/components/camera.h>
|
|
#include <game/client/components/menus.h>
|
|
#include "sounds.h"
|
|
|
|
|
|
CSoundLoading::CSoundLoading(CGameClient *pGameClient, bool Render) :
|
|
m_pGameClient(pGameClient),
|
|
m_Render(Render)
|
|
{
|
|
}
|
|
|
|
void CSoundLoading::Run()
|
|
{
|
|
for(int s = 0; s < g_pData->m_NumSounds; s++)
|
|
{
|
|
for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++)
|
|
{
|
|
int Id = m_pGameClient->Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename);
|
|
g_pData->m_aSounds[s].m_aSounds[i].m_Id = Id;
|
|
}
|
|
|
|
if(m_Render)
|
|
m_pGameClient->m_pMenus->RenderLoading();
|
|
}
|
|
}
|
|
|
|
int CSounds::GetSampleId(int SetId)
|
|
{
|
|
if(!g_Config.m_SndEnable || !Sound()->IsSoundEnabled() || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds)
|
|
return -1;
|
|
|
|
CDataSoundset *pSet = &g_pData->m_aSounds[SetId];
|
|
if(!pSet->m_NumSounds)
|
|
return -1;
|
|
|
|
if(pSet->m_NumSounds == 1)
|
|
return pSet->m_aSounds[0].m_Id;
|
|
|
|
// return random one
|
|
int Id;
|
|
do
|
|
{
|
|
Id = rand() % pSet->m_NumSounds;
|
|
}
|
|
while(Id == pSet->m_Last);
|
|
pSet->m_Last = Id;
|
|
return pSet->m_aSounds[Id].m_Id;
|
|
}
|
|
|
|
void CSounds::OnInit()
|
|
{
|
|
// setup sound channels
|
|
m_MapSoundVolume = g_Config.m_SndMapSoundVolume/100.0f;
|
|
|
|
Sound()->SetChannel(CSounds::CHN_GUI, 1.0f, 0.0f);
|
|
Sound()->SetChannel(CSounds::CHN_MUSIC, 1.0f, 0.0f);
|
|
Sound()->SetChannel(CSounds::CHN_WORLD, 0.9f, 1.0f);
|
|
Sound()->SetChannel(CSounds::CHN_GLOBAL, 1.0f, 0.0f);
|
|
Sound()->SetChannel(CSounds::CHN_MAPSOUND, m_MapSoundVolume, 1.0f);
|
|
|
|
Sound()->SetListenerPos(0.0f, 0.0f);
|
|
|
|
ClearQueue();
|
|
|
|
// load sounds
|
|
if(g_Config.m_ClThreadsoundloading)
|
|
{
|
|
m_pSoundJob = std::make_shared<CSoundLoading>(m_pClient, false);
|
|
m_pClient->Engine()->AddJob(m_pSoundJob);
|
|
m_WaitForSoundJob = true;
|
|
}
|
|
else
|
|
{
|
|
CSoundLoading(m_pClient, true).Run();
|
|
m_WaitForSoundJob = false;
|
|
}
|
|
}
|
|
|
|
void CSounds::OnReset()
|
|
{
|
|
if(Client()->State() >= IClient::STATE_ONLINE)
|
|
{
|
|
Sound()->StopAll();
|
|
ClearQueue();
|
|
}
|
|
}
|
|
|
|
void CSounds::OnStateChange(int NewState, int OldState)
|
|
{
|
|
if(NewState == IClient::STATE_ONLINE || NewState == IClient::STATE_DEMOPLAYBACK)
|
|
OnReset();
|
|
}
|
|
|
|
void CSounds::OnRender()
|
|
{
|
|
// check for sound initialisation
|
|
if(m_WaitForSoundJob)
|
|
{
|
|
if(m_pSoundJob->Status() == IJob::STATE_DONE)
|
|
m_WaitForSoundJob = false;
|
|
else
|
|
return;
|
|
}
|
|
|
|
// set listener pos
|
|
Sound()->SetListenerPos(m_pClient->m_pCamera->m_Center.x, m_pClient->m_pCamera->m_Center.y);
|
|
|
|
// update volume
|
|
float NewMapSoundVol = g_Config.m_SndMapSoundVolume/100.0f;
|
|
if(NewMapSoundVol != m_MapSoundVolume)
|
|
{
|
|
m_MapSoundVolume = NewMapSoundVol;
|
|
Sound()->SetChannel(CSounds::CHN_MAPSOUND, m_MapSoundVolume, 1.0f);
|
|
}
|
|
|
|
// play sound from queue
|
|
if(m_QueuePos > 0)
|
|
{
|
|
int64 Now = time();
|
|
if(m_QueueWaitTime <= Now)
|
|
{
|
|
Play(m_aQueue[0].m_Channel, m_aQueue[0].m_SetId, 1.0f);
|
|
m_QueueWaitTime = Now+time_freq()*3/10; // wait 300ms before playing the next one
|
|
if(--m_QueuePos > 0)
|
|
mem_move(m_aQueue, m_aQueue+1, m_QueuePos*sizeof(QueueEntry));
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSounds::ClearQueue()
|
|
{
|
|
mem_zero(m_aQueue, sizeof(m_aQueue));
|
|
m_QueuePos = 0;
|
|
m_QueueWaitTime = time();
|
|
}
|
|
|
|
void CSounds::Enqueue(int Channel, int SetId)
|
|
{
|
|
// add sound to the queue
|
|
if(m_QueuePos < QUEUE_SIZE)
|
|
{
|
|
if(Channel == CHN_MUSIC || !g_Config.m_ClEditor)
|
|
{
|
|
m_aQueue[m_QueuePos].m_Channel = Channel;
|
|
m_aQueue[m_QueuePos++].m_SetId = SetId;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSounds::PlayAndRecord(int Chn, int SetId, float Vol, vec2 Pos)
|
|
{
|
|
CNetMsg_Sv_SoundGlobal Msg;
|
|
Msg.m_SoundID = SetId;
|
|
Client()->SendPackMsg(&Msg, MSGFLAG_NOSEND|MSGFLAG_RECORD);
|
|
|
|
Play(Chn, SetId, Vol);
|
|
}
|
|
|
|
void CSounds::Play(int Chn, int SetId, float Vol)
|
|
{
|
|
if(Chn == CHN_MUSIC && !g_Config.m_SndMusic)
|
|
return;
|
|
|
|
int SampleId = GetSampleId(SetId);
|
|
if(SampleId == -1)
|
|
return;
|
|
|
|
int Flags = 0;
|
|
if(Chn == CHN_MUSIC)
|
|
Flags = ISound::FLAG_LOOP;
|
|
|
|
Sound()->Play(Chn, SampleId, Flags);
|
|
}
|
|
|
|
void CSounds::PlayAt(int Chn, int SetId, float Vol, vec2 Pos)
|
|
{
|
|
if(Chn == CHN_MUSIC && !g_Config.m_SndMusic)
|
|
return;
|
|
|
|
int SampleId = GetSampleId(SetId);
|
|
if(SampleId == -1)
|
|
return;
|
|
|
|
int Flags = 0;
|
|
if(Chn == CHN_MUSIC)
|
|
Flags = ISound::FLAG_LOOP;
|
|
|
|
Sound()->PlayAt(Chn, SampleId, Flags, Pos.x, Pos.y);
|
|
}
|
|
|
|
void CSounds::Stop(int SetId)
|
|
{
|
|
if(m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds)
|
|
return;
|
|
|
|
CDataSoundset *pSet = &g_pData->m_aSounds[SetId];
|
|
|
|
for(int i = 0; i < pSet->m_NumSounds; i++)
|
|
Sound()->Stop(pSet->m_aSounds[i].m_Id);
|
|
}
|
|
|
|
ISound::CVoiceHandle CSounds::PlaySample(int Chn, int SampleId, float Vol, int Flags)
|
|
{
|
|
if((Chn == CHN_MUSIC && !g_Config.m_SndMusic) || SampleId == -1)
|
|
return ISound::CVoiceHandle();
|
|
|
|
if(Chn == CHN_MUSIC)
|
|
Flags |= ISound::FLAG_LOOP;
|
|
|
|
return Sound()->Play(Chn, SampleId, Flags);
|
|
}
|
|
|
|
ISound::CVoiceHandle CSounds::PlaySampleAt(int Chn, int SampleId, float Vol, vec2 Pos, int Flags)
|
|
{
|
|
if((Chn == CHN_MUSIC && !g_Config.m_SndMusic) || SampleId == -1)
|
|
return ISound::CVoiceHandle();
|
|
|
|
if(Chn == CHN_MUSIC)
|
|
Flags |= ISound::FLAG_LOOP;
|
|
|
|
return Sound()->PlayAt(Chn, SampleId, Flags, Pos.x, Pos.y);
|
|
}
|