2010-11-20 10:37:14 +00:00
|
|
|
/* (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. */
|
2011-08-31 11:56:04 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
#include "sounds.h"
|
2022-06-23 17:59:38 +00:00
|
|
|
|
2011-02-27 16:56:03 +00:00
|
|
|
#include <engine/engine.h>
|
2010-09-21 22:51:32 +00:00
|
|
|
#include <engine/shared/config.h>
|
2020-09-26 19:41:58 +00:00
|
|
|
#include <engine/sound.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/client/components/camera.h>
|
2011-02-27 16:56:03 +00:00
|
|
|
#include <game/client/components/menus.h>
|
2020-09-26 19:41:58 +00:00
|
|
|
#include <game/client/gameclient.h>
|
|
|
|
#include <game/generated/client_data.h>
|
2022-06-23 17:59:38 +00:00
|
|
|
#include <game/localization.h>
|
2011-02-27 16:56:03 +00:00
|
|
|
|
2017-11-23 14:47:38 +00:00
|
|
|
CSoundLoading::CSoundLoading(CGameClient *pGameClient, bool Render) :
|
|
|
|
m_pGameClient(pGameClient),
|
|
|
|
m_Render(Render)
|
2011-02-27 16:56:03 +00:00
|
|
|
{
|
2017-11-23 14:47:38 +00:00
|
|
|
}
|
2011-02-27 16:56:03 +00:00
|
|
|
|
2017-11-23 14:47:38 +00:00
|
|
|
void CSoundLoading::Run()
|
2011-02-27 16:56:03 +00:00
|
|
|
{
|
|
|
|
for(int s = 0; s < g_pData->m_NumSounds; s++)
|
|
|
|
{
|
2022-06-23 17:59:38 +00:00
|
|
|
const char *pLoadingCaption = Localize("Loading DDNet Client");
|
|
|
|
const char *pLoadingContent = Localize("Loading sound files");
|
|
|
|
|
2011-02-27 16:56:03 +00:00
|
|
|
for(int i = 0; i < g_pData->m_aSounds[s].m_NumSounds; i++)
|
|
|
|
{
|
2017-11-23 14:47:38 +00:00
|
|
|
int Id = m_pGameClient->Sound()->LoadWV(g_pData->m_aSounds[s].m_aSounds[i].m_pFilename);
|
2011-02-27 16:56:03 +00:00
|
|
|
g_pData->m_aSounds[s].m_aSounds[i].m_Id = Id;
|
2022-04-02 11:37:59 +00:00
|
|
|
// try to render a frame
|
|
|
|
if(m_Render)
|
2022-06-23 17:59:38 +00:00
|
|
|
m_pGameClient->m_Menus.RenderLoading(pLoadingCaption, pLoadingContent, 0);
|
2011-02-27 16:56:03 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 14:47:38 +00:00
|
|
|
if(m_Render)
|
2022-06-23 17:59:38 +00:00
|
|
|
m_pGameClient->m_Menus.RenderLoading(pLoadingCaption, pLoadingContent, 1);
|
2011-02-27 16:56:03 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-06 18:38:40 +00:00
|
|
|
|
|
|
|
int CSounds::GetSampleId(int SetId)
|
|
|
|
{
|
|
|
|
if(!g_Config.m_SndEnable || !Sound()->IsSoundEnabled() || m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds)
|
|
|
|
return -1;
|
2015-07-09 00:08:14 +00:00
|
|
|
|
2012-01-06 18:38:40 +00:00
|
|
|
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;
|
2020-09-26 19:41:58 +00:00
|
|
|
} while(Id == pSet->m_Last);
|
2012-01-06 18:38:40 +00:00
|
|
|
pSet->m_Last = Id;
|
|
|
|
return pSet->m_aSounds[Id].m_Id;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CSounds::OnInit()
|
2008-08-29 05:34:18 +00:00
|
|
|
{
|
|
|
|
// setup sound channels
|
2020-10-09 21:14:20 +00:00
|
|
|
m_GuiSoundVolume = g_Config.m_SndChatSoundVolume / 100.0f;
|
|
|
|
m_GameSoundVolume = g_Config.m_SndGameSoundVolume / 100.0f;
|
2020-09-26 19:41:58 +00:00
|
|
|
m_MapSoundVolume = g_Config.m_SndMapSoundVolume / 100.0f;
|
2020-09-30 08:06:54 +00:00
|
|
|
m_BackgroundMusicVolume = g_Config.m_SndBackgroundMusicVolume / 100.0f;
|
2014-10-12 15:02:47 +00:00
|
|
|
|
2020-10-09 21:14:20 +00:00
|
|
|
Sound()->SetChannel(CSounds::CHN_GUI, m_GuiSoundVolume, 0.0f);
|
2020-09-30 08:06:54 +00:00
|
|
|
Sound()->SetChannel(CSounds::CHN_MUSIC, m_BackgroundMusicVolume, 1.0f);
|
2020-10-09 21:14:20 +00:00
|
|
|
Sound()->SetChannel(CSounds::CHN_WORLD, 0.9f * m_GameSoundVolume, 1.0f);
|
|
|
|
Sound()->SetChannel(CSounds::CHN_GLOBAL, m_GameSoundVolume, 0.0f);
|
2014-10-23 13:53:23 +00:00
|
|
|
Sound()->SetChannel(CSounds::CHN_MAPSOUND, m_MapSoundVolume, 1.0f);
|
2008-08-30 08:01:29 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Sound()->SetListenerPos(0.0f, 0.0f);
|
|
|
|
|
|
|
|
ClearQueue();
|
2011-02-27 16:56:03 +00:00
|
|
|
|
|
|
|
// load sounds
|
|
|
|
if(g_Config.m_ClThreadsoundloading)
|
|
|
|
{
|
2017-11-23 14:47:38 +00:00
|
|
|
m_pSoundJob = std::make_shared<CSoundLoading>(m_pClient, false);
|
|
|
|
m_pClient->Engine()->AddJob(m_pSoundJob);
|
2011-02-27 16:56:03 +00:00
|
|
|
m_WaitForSoundJob = true;
|
2022-06-23 17:59:38 +00:00
|
|
|
m_pClient->m_Menus.RenderLoading(Localize("Loading DDNet Client"), Localize("Loading sound files"), 0);
|
2011-02-27 16:56:03 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-23 14:47:38 +00:00
|
|
|
CSoundLoading(m_pClient, true).Run();
|
2011-02-27 16:56:03 +00:00
|
|
|
m_WaitForSoundJob = false;
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSounds::OnReset()
|
|
|
|
{
|
2011-06-27 21:26:01 +00:00
|
|
|
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();
|
2008-08-29 05:34:18 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CSounds::OnRender()
|
2008-08-29 05:34:18 +00:00
|
|
|
{
|
2011-02-27 16:56:03 +00:00
|
|
|
// check for sound initialisation
|
2011-04-13 18:00:54 +00:00
|
|
|
if(m_WaitForSoundJob)
|
|
|
|
{
|
2017-11-23 14:47:38 +00:00
|
|
|
if(m_pSoundJob->Status() == IJob::STATE_DONE)
|
2011-04-13 18:00:54 +00:00
|
|
|
m_WaitForSoundJob = false;
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
}
|
2011-02-27 16:56:03 +00:00
|
|
|
|
2018-07-10 09:29:02 +00:00
|
|
|
// set listener pos
|
2021-07-12 09:43:56 +00:00
|
|
|
Sound()->SetListenerPos(m_pClient->m_Camera.m_Center.x, m_pClient->m_Camera.m_Center.y);
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2014-10-12 15:02:47 +00:00
|
|
|
// update volume
|
2020-10-09 21:14:20 +00:00
|
|
|
float NewGuiSoundVol = g_Config.m_SndChatSoundVolume / 100.0f;
|
|
|
|
if(NewGuiSoundVol != m_GuiSoundVolume)
|
|
|
|
{
|
|
|
|
m_GuiSoundVolume = NewGuiSoundVol;
|
|
|
|
Sound()->SetChannel(CSounds::CHN_GUI, m_GuiSoundVolume, 1.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
float NewGameSoundVol = g_Config.m_SndGameSoundVolume / 100.0f;
|
|
|
|
if(NewGameSoundVol != m_GameSoundVolume)
|
|
|
|
{
|
|
|
|
m_GameSoundVolume = NewGameSoundVol;
|
|
|
|
Sound()->SetChannel(CSounds::CHN_WORLD, 0.9f * m_GameSoundVolume, 1.0f);
|
|
|
|
Sound()->SetChannel(CSounds::CHN_GLOBAL, m_GameSoundVolume, 1.0f);
|
|
|
|
}
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
float NewMapSoundVol = g_Config.m_SndMapSoundVolume / 100.0f;
|
2014-10-23 13:53:23 +00:00
|
|
|
if(NewMapSoundVol != m_MapSoundVolume)
|
2014-10-12 15:02:47 +00:00
|
|
|
{
|
2014-10-23 13:53:23 +00:00
|
|
|
m_MapSoundVolume = NewMapSoundVol;
|
|
|
|
Sound()->SetChannel(CSounds::CHN_MAPSOUND, m_MapSoundVolume, 1.0f);
|
2014-10-12 15:02:47 +00:00
|
|
|
}
|
|
|
|
|
2020-09-30 08:06:54 +00:00
|
|
|
float NewBackgroundMusicVol = g_Config.m_SndBackgroundMusicVolume / 100.0f;
|
|
|
|
if(NewBackgroundMusicVol != m_BackgroundMusicVolume)
|
|
|
|
{
|
|
|
|
m_BackgroundMusicVolume = NewBackgroundMusicVol;
|
|
|
|
Sound()->SetChannel(CSounds::CHN_MUSIC, m_BackgroundMusicVolume, 1.0f);
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// play sound from queue
|
|
|
|
if(m_QueuePos > 0)
|
|
|
|
{
|
2021-06-23 05:05:49 +00:00
|
|
|
int64_t Now = time();
|
2010-05-29 07:25:38 +00:00
|
|
|
if(m_QueueWaitTime <= Now)
|
|
|
|
{
|
2012-01-06 18:38:40 +00:00
|
|
|
Play(m_aQueue[0].m_Channel, m_aQueue[0].m_SetId, 1.0f);
|
2020-09-26 19:41:58 +00:00
|
|
|
m_QueueWaitTime = Now + time_freq() * 3 / 10; // wait 300ms before playing the next one
|
2010-05-29 07:25:38 +00:00
|
|
|
if(--m_QueuePos > 0)
|
2020-09-26 19:41:58 +00:00
|
|
|
mem_move(m_aQueue, m_aQueue + 1, m_QueuePos * sizeof(QueueEntry));
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
}
|
2008-08-29 05:34:18 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CSounds::ClearQueue()
|
2009-01-11 15:51:43 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
mem_zero(m_aQueue, sizeof(m_aQueue));
|
|
|
|
m_QueuePos = 0;
|
2016-08-30 23:39:59 +00:00
|
|
|
m_QueueWaitTime = time();
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2011-04-13 18:00:54 +00:00
|
|
|
void CSounds::Enqueue(int Channel, int SetId)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2022-08-28 09:53:16 +00:00
|
|
|
if(m_pClient->m_SuppressEvents)
|
|
|
|
return;
|
|
|
|
if(m_QueuePos >= QUEUE_SIZE)
|
|
|
|
return;
|
|
|
|
if(Channel != CHN_MUSIC && g_Config.m_ClEditor)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_aQueue[m_QueuePos].m_Channel = Channel;
|
|
|
|
m_aQueue[m_QueuePos++].m_SetId = SetId;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
void CSounds::PlayAndRecord(int Channel, int SetId, float Vol, vec2 Pos)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
|
|
|
CNetMsg_Sv_SoundGlobal Msg;
|
2011-02-12 10:40:36 +00:00
|
|
|
Msg.m_SoundID = SetId;
|
2022-01-21 00:54:14 +00:00
|
|
|
Client()->SendPackMsgActive(&Msg, MSGFLAG_NOSEND | MSGFLAG_RECORD);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
Play(Channel, SetId, Vol);
|
2009-01-11 15:51:43 +00:00
|
|
|
}
|
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
void CSounds::Play(int Channel, int SetId, float Vol)
|
2008-08-29 05:34:18 +00:00
|
|
|
{
|
2022-08-28 09:53:16 +00:00
|
|
|
if(m_pClient->m_SuppressEvents)
|
|
|
|
return;
|
2022-01-22 13:12:59 +00:00
|
|
|
if(Channel == CHN_MUSIC && !g_Config.m_SndMusic)
|
2010-05-29 07:25:38 +00:00
|
|
|
return;
|
|
|
|
|
2012-01-06 18:38:40 +00:00
|
|
|
int SampleId = GetSampleId(SetId);
|
|
|
|
if(SampleId == -1)
|
2008-08-29 05:34:18 +00:00
|
|
|
return;
|
2011-08-11 08:59:14 +00:00
|
|
|
|
2011-04-13 18:00:54 +00:00
|
|
|
int Flags = 0;
|
2022-01-22 13:12:59 +00:00
|
|
|
if(Channel == CHN_MUSIC)
|
2011-04-13 18:00:54 +00:00
|
|
|
Flags = ISound::FLAG_LOOP;
|
2008-08-29 05:34:18 +00:00
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
Sound()->Play(Channel, SampleId, Flags);
|
2012-01-06 18:38:40 +00:00
|
|
|
}
|
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
void CSounds::PlayAt(int Channel, int SetId, float Vol, vec2 Pos)
|
2012-01-06 18:38:40 +00:00
|
|
|
{
|
2022-08-28 09:53:16 +00:00
|
|
|
if(m_pClient->m_SuppressEvents)
|
|
|
|
return;
|
2022-01-22 13:12:59 +00:00
|
|
|
if(Channel == CHN_MUSIC && !g_Config.m_SndMusic)
|
2012-01-06 18:38:40 +00:00
|
|
|
return;
|
2015-07-09 00:08:14 +00:00
|
|
|
|
2012-01-06 18:38:40 +00:00
|
|
|
int SampleId = GetSampleId(SetId);
|
|
|
|
if(SampleId == -1)
|
2008-08-29 05:34:18 +00:00
|
|
|
return;
|
|
|
|
|
2012-01-06 18:38:40 +00:00
|
|
|
int Flags = 0;
|
2022-01-22 13:12:59 +00:00
|
|
|
if(Channel == CHN_MUSIC)
|
2012-01-06 18:38:40 +00:00
|
|
|
Flags = ISound::FLAG_LOOP;
|
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
Sound()->PlayAt(Channel, SampleId, Flags, Pos.x, Pos.y);
|
2008-08-29 05:34:18 +00:00
|
|
|
}
|
2011-04-13 18:00:54 +00:00
|
|
|
|
|
|
|
void CSounds::Stop(int SetId)
|
|
|
|
{
|
|
|
|
if(m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds)
|
|
|
|
return;
|
2011-08-11 08:59:14 +00:00
|
|
|
|
2022-06-26 20:38:47 +00:00
|
|
|
const CDataSoundset *pSet = &g_pData->m_aSounds[SetId];
|
2011-04-13 18:00:54 +00:00
|
|
|
for(int i = 0; i < pSet->m_NumSounds; i++)
|
2022-06-26 20:38:47 +00:00
|
|
|
if(pSet->m_aSounds[i].m_Id != -1)
|
|
|
|
Sound()->Stop(pSet->m_aSounds[i].m_Id);
|
2011-04-13 18:00:54 +00:00
|
|
|
}
|
2014-10-10 17:10:57 +00:00
|
|
|
|
2022-06-26 20:06:22 +00:00
|
|
|
bool CSounds::IsPlaying(int SetId)
|
|
|
|
{
|
|
|
|
if(m_WaitForSoundJob || SetId < 0 || SetId >= g_pData->m_NumSounds)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const CDataSoundset *pSet = &g_pData->m_aSounds[SetId];
|
|
|
|
for(int i = 0; i < pSet->m_NumSounds; i++)
|
|
|
|
if(pSet->m_aSounds[i].m_Id != -1 && Sound()->IsPlaying(pSet->m_aSounds[i].m_Id))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
ISound::CVoiceHandle CSounds::PlaySample(int Channel, int SampleId, float Vol, int Flags)
|
2014-10-10 17:10:57 +00:00
|
|
|
{
|
2022-01-22 13:12:59 +00:00
|
|
|
if((Channel == CHN_MUSIC && !g_Config.m_SndMusic) || SampleId == -1)
|
2014-10-12 14:12:13 +00:00
|
|
|
return ISound::CVoiceHandle();
|
2014-10-10 17:10:57 +00:00
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
if(Channel == CHN_MUSIC)
|
2014-10-10 17:10:57 +00:00
|
|
|
Flags |= ISound::FLAG_LOOP;
|
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
return Sound()->Play(Channel, SampleId, Flags);
|
2014-10-10 17:10:57 +00:00
|
|
|
}
|
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
ISound::CVoiceHandle CSounds::PlaySampleAt(int Channel, int SampleId, float Vol, vec2 Pos, int Flags)
|
2014-10-10 17:10:57 +00:00
|
|
|
{
|
2022-01-22 13:12:59 +00:00
|
|
|
if((Channel == CHN_MUSIC && !g_Config.m_SndMusic) || SampleId == -1)
|
2014-10-12 14:12:13 +00:00
|
|
|
return ISound::CVoiceHandle();
|
2014-10-10 17:10:57 +00:00
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
if(Channel == CHN_MUSIC)
|
2014-10-10 17:10:57 +00:00
|
|
|
Flags |= ISound::FLAG_LOOP;
|
|
|
|
|
2022-01-22 13:12:59 +00:00
|
|
|
return Sound()->PlayAt(Channel, SampleId, Flags, Pos.x, Pos.y);
|
2014-10-23 13:53:23 +00:00
|
|
|
}
|