Merge pull request #4 from amun3808/new-audio-system

New sound system & removed miles
This commit is contained in:
d1str4ught
2025-08-27 21:41:38 +02:00
committed by GitHub
58 changed files with 94365 additions and 9806 deletions

8421
extern/include/MSS.H vendored

File diff suppressed because it is too large Load Diff

2
extern/include/miniaudio.c vendored Normal file
View File

@@ -0,0 +1,2 @@
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"

93468
extern/include/miniaudio.h vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,5 @@
add_subdirectory(DirectX)
add_subdirectory(Granny)
add_subdirectory(MilesSoundSystem)
add_subdirectory(Python)
add_subdirectory(SpeedTree)
add_subdirectory(WebView)

View File

@@ -1,6 +0,0 @@
add_library(MilesSoundSystem STATIC IMPORTED GLOBAL)
set_target_properties(MilesSoundSystem PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/extern/include"
IMPORTED_LOCATION "${CMAKE_CURRENT_LIST_DIR}/mss64.lib"
)

Binary file not shown.

View File

@@ -0,0 +1,9 @@
file(GLOB_RECURSE FILE_SOURCES "*.h" "*.c" "*.cpp")
add_library(AudioLib STATIC ${FILE_SOURCES})
target_link_libraries(AudioLib
lzo2
)
GroupSourcesByFolder(AudioLib)

View File

@@ -0,0 +1,175 @@
#include "stdafx.h"
#include "MaSoundInstance.h"
#include <miniaudio.c>
bool MaSoundInstance::InitFromBuffer(ma_engine& engine, const std::vector<uint8_t>& buffer, const std::string& identity)
{
if (!m_Initialized)
{
ma_decoder_config decoderConfig = ma_decoder_config_init_default();
ma_result result = ma_decoder_init_memory(buffer.data(), buffer.size(),
&decoderConfig, &m_Decoder);
if (!MD_ASSERT(result == MA_SUCCESS))
{
TraceError("Failed to initialize decoder memory.");
return false;
}
ma_sound_config soundConfig = ma_sound_config_init();
soundConfig.pDataSource = &m_Decoder;
result = ma_sound_init_ex(&engine, &soundConfig, &m_Sound);
if (!MD_ASSERT(result == MA_SUCCESS))
{
TraceError("Failed to initialize sound.");
return false;
}
m_Identity = identity;
m_Initialized = true;
}
return m_Initialized;
}
// Basically c&p
bool MaSoundInstance::InitFromFile(ma_engine& engine, const std::string& filePathOnDisk)
{
if (!m_Initialized)
{
ma_decoder_config decoderConfig = ma_decoder_config_init_default();
ma_result result = ma_decoder_init_file(filePathOnDisk.c_str(), &decoderConfig, &m_Decoder);
if (!MD_ASSERT(result == MA_SUCCESS))
{
TraceError("Failed to initialize sound file decoder.");
return false;
}
ma_sound_config soundConfig = ma_sound_config_init();
soundConfig.pDataSource = &m_Decoder;
result = ma_sound_init_ex(&engine, &soundConfig, &m_Sound);
if (!MD_ASSERT(result == MA_SUCCESS))
{
TraceError("Failed to initialize sound.");
return false;
}
m_Identity = filePathOnDisk;
m_Initialized = true;
}
return m_Initialized;
}
void MaSoundInstance::Destroy()
{
if (m_Initialized)
{
ma_sound_uninit(&m_Sound);
ma_decoder_uninit(&m_Decoder);
}
m_Initialized = false;
m_Identity = "";
m_FadeTargetVolume = 0;
m_FadeRatePerFrame = 0;
}
bool MaSoundInstance::IsInitialized() const
{
return m_Initialized;
}
bool MaSoundInstance::IsPlaying() const
{
return ma_sound_is_playing(&m_Sound) == MA_TRUE;
}
bool MaSoundInstance::Play()
{
return m_Initialized && ma_sound_seek_to_pcm_frame(&m_Sound, 0) == MA_SUCCESS && ma_sound_start(&m_Sound) == MA_SUCCESS;
}
bool MaSoundInstance::Resume()
{
return m_Initialized && ma_sound_start(&m_Sound) == MA_SUCCESS;
}
bool MaSoundInstance::Stop()
{
return m_Initialized && ma_sound_stop(&m_Sound) == MA_SUCCESS;
}
void MaSoundInstance::Loop()
{
ma_sound_set_looping(&m_Sound, MA_TRUE);
}
float MaSoundInstance::GetVolume() const
{
return ma_sound_get_volume(&m_Sound);
}
void MaSoundInstance::SetVolume(float volume)
{
ma_sound_set_volume(&m_Sound, volume);
}
void MaSoundInstance::SetPitch(float pitch)
{
ma_sound_set_pitch(&m_Sound, pitch);
}
void MaSoundInstance::SetPosition(float x, float y, float z)
{
ma_sound_set_position(&m_Sound, x, y, z);
}
const std::string& MaSoundInstance::GetIdentity() const
{
return m_Identity;
}
void MaSoundInstance::Config3D(bool toggle, float minDist, float maxDist, float rolloff)
{
ma_sound_set_spatialization_enabled(&m_Sound, toggle);
ma_sound_set_rolloff(&m_Sound, 1.0f);
ma_sound_set_min_distance(&m_Sound, minDist);
ma_sound_set_max_distance(&m_Sound, maxDist);
ma_sound_set_attenuation_model(&m_Sound, ma_attenuation_model_linear);
}
void MaSoundInstance::Fade(float toVolume, float secDurationFromMinMax)
{
toVolume = std::clamp<float>(toVolume, 0.0f, 1.0f);
m_FadeTargetVolume = toVolume;
float rate = 1.0f / 61.0f / secDurationFromMinMax;
m_FadeRatePerFrame = GetVolume() > toVolume ? -rate : rate;
}
void MaSoundInstance::StopFading()
{
m_FadeRatePerFrame = 0;
}
bool MaSoundInstance::IsFading() const
{
return m_FadeRatePerFrame != 0;
}
void MaSoundInstance::Update(float volumeFactor) // volume factor is the user's volume
{
if (m_FadeRatePerFrame != 0)
{
float targetVolume = std::clamp<float>(m_FadeTargetVolume * volumeFactor, 0.0f, 1.0f);
float volume = std::clamp<float>(GetVolume() + (m_FadeRatePerFrame * volumeFactor), 0.0f, 1.0f);
if ((m_FadeRatePerFrame > 0 && volume >= targetVolume) || (m_FadeRatePerFrame < 0 && volume <= targetVolume))
{
volume = m_FadeTargetVolume * volumeFactor;
m_FadeRatePerFrame = 0.0f;
if (volume <= 0.0f)
ma_sound_stop(&m_Sound);
}
ma_sound_set_volume(&m_Sound, volume);
}
}

View File

@@ -0,0 +1,54 @@
#pragma once
#include <miniaudio.h>
inline constexpr float CS_CLIENT_FPS = 61.0f;
class MaSoundInstance
{
public:
bool InitFromBuffer(ma_engine& engine, const std::vector<uint8_t>& buffer, const std::string& identity);
bool InitFromFile(ma_engine& engine, const std::string& filePathOnDisk);
void Destroy();
bool IsInitialized() const;
bool IsPlaying() const;
bool Play();
bool Resume();
bool Stop();
void Loop();
float GetVolume() const;
void SetVolume(float volume);
void SetPitch(float pitch);
void SetPosition(float x, float y, float z);
const std::string& GetIdentity() const;
void Config3D(bool toggle, float minDist = 100.0f/*1m*/, float maxDist = 4000.0f/*40m*/, float rolloff = 1.0f);
void Fade(float toVolume, float secDurationFromMinMax);
void StopFading();
bool IsFading() const;
void Update(float volumeFactor = 1.0f);
private:
std::string m_Identity;
ma_sound m_Sound{};
ma_decoder m_Decoder{};
bool m_Initialized{};
float m_FadeTargetVolume{};
float m_FadeRatePerFrame{};
};

View File

@@ -0,0 +1,268 @@
#include "stdafx.h"
#include "SoundEngine.h"
#include "EterBase/Random.h"
#include "EterBase/Timer.h"
#include "Eterpack/EterPackManager.h"
SoundEngine::SoundEngine()
{
}
SoundEngine::~SoundEngine()
{
for (auto& [name, instance] : m_Sounds2D)
instance.Destroy();
for (auto& instance : m_Sounds3D)
instance.Destroy();
ma_engine_uninit(&m_Engine);
m_Files.clear();
m_Sounds2D.clear();
}
bool SoundEngine::Initialize()
{
if (!MD_ASSERT(ma_engine_init(NULL, &m_Engine) == MA_SUCCESS))
{
TraceError("SoundEngine::Initialize: Failed to initialize engine.");
return false;
}
SetListenerPosition(0.0f, 0.0f, 0.0f);
SetListenerOrientation(0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f);
return true;
}
void SoundEngine::SetSoundVolume(float volume)
{
m_SoundVolume = std::clamp<float>(volume, 0.0, 1.0);
}
bool SoundEngine::PlaySound2D(const std::string& name)
{
if (!Internal_LoadSoundFromPack(name))
return false;
auto& instance = m_Sounds2D[name]; // 2d sounds are persistent, no need to destroy
instance.InitFromBuffer(m_Engine, m_Files[name], name);
instance.Config3D(false);
instance.SetVolume(m_SoundVolume);
return instance.Play();
}
MaSoundInstance* SoundEngine::PlaySound3D(const std::string& name, float fx, float fy, float fz)
{
if (auto instance = Internal_GetInstance3D(name))
{
constexpr float minDist = 100.0f; // 1m
constexpr float maxDist = 4000.0f; // 40m
instance->SetPosition(fx, fy, fz);
instance->Config3D(true, minDist, maxDist, 1.0f);
instance->SetVolume(m_SoundVolume);
instance->Play();
return instance;
}
return nullptr;
}
MaSoundInstance* SoundEngine::PlayAmbienceSound3D(float fx, float fy, float fz, const std::string& name, int loopCount)
{
auto vec3 = ma_engine_listener_get_position(&m_Engine, 0);
float dx = fx - vec3.x;
float dy = fy - vec3.y;
float dz = fz - vec3.z;
float distance = sqrtf(dx * dx + dy * dy + dz * dz);
return PlaySound3D(name, fx, fy, fz);
}
void SoundEngine::StopAllSound3D()
{
for (auto& instance : m_Sounds3D)
instance.Stop();
}
void SoundEngine::UpdateSoundInstance(float fx, float fy, float fz, uint32_t dwcurFrame, const NSound::TSoundInstanceVector* c_pSoundInstanceVector, bool checkFrequency, bool isMain)
{
for (uint32_t i = 0; i < c_pSoundInstanceVector->size(); ++i)
{
const NSound::TSoundInstance& c_rSoundInstance = c_pSoundInstanceVector->at(i);
if (c_rSoundInstance.dwFrame == dwcurFrame)
{
if (checkFrequency)
{
float& lastPlay = m_PlaySoundHistoryMap[c_rSoundInstance.strSoundFileName];
float diff = CTimer::Instance().GetCurrentSecond() - lastPlay;
if (CTimer::Instance().GetCurrentSecond() - lastPlay < 0.3f)
return;
lastPlay = CTimer::Instance().GetCurrentSecond();
}
if (isMain) // Sounds coming from main instance will always be played in 2d
{
// float volume = 0.9f + frandom(-0.1f, 0.1f);
// instance->SetPitch(pitch); // Should we play around with pitch a bit?
PlaySound2D(c_rSoundInstance.strSoundFileName);
}
else
{
// float volume = 0.9f + frandom(-0.1f, 0.1f);
// instance->SetPitch(pitch); // Should we play around with pitch a bit?
PlaySound3D(c_rSoundInstance.strSoundFileName, fx, fy, fz);
}
}
}
}
bool SoundEngine::FadeInMusic(const std::string& path, float targetVolume /* 1.0f by default */, float fadeInDurationSecondsFromMin)
{
if (path.empty())
return false;
auto& fadeOutMusic = m_Music[m_CurrentMusicIndex];
if (fadeOutMusic.IsPlaying() && path == fadeOutMusic.GetIdentity())
{
fadeOutMusic.Fade(targetVolume, fadeInDurationSecondsFromMin);
return fadeOutMusic.Resume();
}
// We're basically just swapping
FadeOutMusic(fadeOutMusic.GetIdentity());
m_CurrentMusicIndex = int(!m_CurrentMusicIndex);
auto& music = m_Music[m_CurrentMusicIndex];
music.Destroy();
music.InitFromFile(m_Engine, path);
music.Config3D(false);
music.Loop();
music.SetVolume(0.0f);
music.Fade(targetVolume, fadeInDurationSecondsFromMin);
return music.Play();
}
void SoundEngine::FadeOutMusic(const std::string& name, float targetVolume, float fadeOutDurationSecondsFromMax)
{
for (auto& music : m_Music)
{
if (music.GetIdentity() == name)
music.Fade(targetVolume, fadeOutDurationSecondsFromMax);
}
}
void SoundEngine::FadeOutAllMusic()
{
for (auto& music : m_Music)
FadeOutMusic(music.GetIdentity());
}
void SoundEngine::SetMusicVolume(float volume)
{
m_MusicVolume = std::clamp<float>(volume, 0.0f, 1.0f);
for (auto& music : m_Music)
{
if (music.IsInitialized() && !music.IsFading()) // fading music will update itself
music.SetVolume(m_MusicVolume);
}
}
void SoundEngine::SaveVolume(bool isMinimized)
{
constexpr float ratePerSecond = 1.0f / CS_CLIENT_FPS;
// 1.0 to 0 in 1s if minimized, 3s if just out of focus
const float durationOnFullVolume = isMinimized ? 1.0 : 3.0f;
float outOfFocusVolume = 0.35f;
if (m_MasterVolume <= outOfFocusVolume)
outOfFocusVolume = m_MasterVolume;
m_MasterVolumeFadeTarget = isMinimized ? 0 : outOfFocusVolume;
m_MasterVolumeFadeRatePerFrame = -ratePerSecond / durationOnFullVolume;
}
void SoundEngine::RestoreVolume()
{
constexpr float ratePerSecond = 1.0f / CS_CLIENT_FPS;
constexpr float durationToFullVolume = 4.0f; // 0 to 1.0 in 4s
m_MasterVolumeFadeTarget = m_MasterVolume;
m_MasterVolumeFadeRatePerFrame = ratePerSecond / durationToFullVolume;
}
void SoundEngine::SetMasterVolume(float volume)
{
m_MasterVolume = volume;
ma_engine_set_volume(&m_Engine, volume);
}
void SoundEngine::SetListenerPosition(float x, float y, float z)
{
ma_engine_listener_set_position(&m_Engine, 0, x, y, z);
}
void SoundEngine::SetListenerOrientation(float forwardX, float forwardY, float forwardZ,
float upX, float upY, float upZ)
{
ma_engine_listener_set_direction(&m_Engine, 0, forwardX, forwardY, forwardZ);
ma_engine_listener_set_world_up(&m_Engine, 0, upX, upY, upZ);
}
void SoundEngine::SetListenerVelocity(float x, float y, float z)
{
ma_engine_listener_set_velocity(&m_Engine, 0, x, y, z);
}
void SoundEngine::Update()
{
for (auto& music : m_Music)
music.Update(m_MusicVolume);
if (m_MasterVolumeFadeRatePerFrame)
{
float volume = ma_engine_get_volume(&m_Engine) + m_MasterVolumeFadeRatePerFrame;
if ((m_MasterVolumeFadeRatePerFrame > 0 && volume >= m_MasterVolumeFadeTarget) || (m_MasterVolumeFadeRatePerFrame < 0 && volume <= m_MasterVolumeFadeTarget))
{
volume = m_MasterVolumeFadeTarget;
m_MasterVolumeFadeRatePerFrame = 0.0f;
}
ma_engine_set_volume(&m_Engine, volume);
}
}
MaSoundInstance* SoundEngine::Internal_GetInstance3D(const std::string& name)
{
if (Internal_LoadSoundFromPack(name))
{
for (auto& instance : m_Sounds3D)
{
if (!instance.IsPlaying())
{
instance.Destroy();
instance.InitFromBuffer(m_Engine, m_Files[name], name);
return &instance;
}
}
}
return nullptr;
}
bool SoundEngine::Internal_LoadSoundFromPack(const std::string& name)
{
if (m_Files.find(name) == m_Files.end())
{
LPCVOID soundData;
CMappedFile soundFile;
if (!CEterPackManager::Instance().Get(soundFile, name.c_str(), &soundData))
{
TraceError("Internal_LoadSoundFromPack: SoundEngine: Failed to register file '%s' - not found.", name.c_str());
return false;
}
auto& buffer = m_Files[name];
buffer.resize(soundFile.Size());
memcpy(buffer.data(), soundData, soundFile.Size());
}
return true;
}

View File

@@ -0,0 +1,96 @@
#pragma once
#include "../eterBase/Singleton.h"
#include "Type.h"
#include "MaSoundInstance.h"
//#include <miniaudio.h>
#include <array>
#include <unordered_map>
struct SoundFile
{
std::string name;
std::vector<std::byte> buffer; // raw file data.
};
class SoundEngine : public CSingleton<SoundEngine>
{
public:
enum ESoundConfig
{
SOUND_INSTANCE_3D_MAX_NUM = 32,
};
// enum ESoundType
// {
// SOUND_TYPE_INTERFACE, // Interface sounds. Loaded on game opening, unloaded when the game ends.
// SOUND_TYPE_CHARACTER, // Character sounds(hit, damage, etc). Loaded on login, unloaded when the game ends.
// SOUND_TYPE_MONSTER, // monster attacks, hits, etc. Loaded and unloaded on warp
// SOUND_TYPE_AMBIENCE, // Wind, rain, birds, etc. Loaded and unloaded on warp
// SOUND_TYPE_MUSIC, // Bg music played on demand
// SOUND_TYPE_MAX_NUM,
// };
public:
SoundEngine();
~SoundEngine();
bool Initialize();
void SetSoundVolume(float volume);
bool PlaySound2D(const std::string& name);
MaSoundInstance* PlaySound3D(const std::string& name, float fx, float fy, float fz);
MaSoundInstance* PlayAmbienceSound3D(float fx, float fy, float fz, const std::string& name, int loopCount = 1);
void StopAllSound3D();
void UpdateSoundInstance(float fx, float fy, float fz, uint32_t dwcurFrame, const NSound::TSoundInstanceVector* c_pSoundInstanceVector, bool checkFrequency = false, bool isMain = false);
bool FadeInMusic(const std::string& path, float targetVolume = 1.0f, float fadeInDurationSecondsFromMin = 1.5f);
void FadeOutMusic(const std::string& name, float targetVolume = 0.0f, float fadeOutDurationSecondsFromMax = 1.5f);
void FadeOutAllMusic();
void SetMusicVolume(float volume);
void SaveVolume(bool isMinimized);
void RestoreVolume();
void SetMasterVolume(float volume);
void SetListenerPosition(float x, float y, float z);
void SetListenerOrientation(float forwardX, float forwardY, float forwardZ,
float upX, float upY, float upZ);
void SetListenerVelocity(float x, float y, float z);
void Update();
private:
MaSoundInstance* Internal_GetInstance3D(const std::string& name);
bool Internal_LoadSoundFromPack(const std::string& name);
private:
ma_engine m_Engine{};
std::unordered_map<std::string, std::vector<uint8_t>> m_Files;
std::unordered_map<std::string, MaSoundInstance> m_Sounds2D;
std::array<MaSoundInstance, SOUND_INSTANCE_3D_MAX_NUM> m_Sounds3D;
std::unordered_map<std::string, float> m_PlaySoundHistoryMap;
// One song at a time, but holding both current and previous for graceful fading
std::array<MaSoundInstance, 2> m_Music;
int m_CurrentMusicIndex{};
float m_MusicVolume{ 1.0 };
float m_SoundVolume{ 1.0 };
float m_MasterVolume{ 1.0 };
float m_MasterVolumeFadeTarget{};
float m_MasterVolumeFadeRatePerFrame{};
};

9
src/AudioLib/Stdafx.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
//#include <windows.h>
#include "../eterBase/CRC32.h"
#include "../eterBase/Utils.h"
#include "../eterBase/Debug.h"
#include <algorithm>

138
src/AudioLib/Type.cpp Normal file
View File

@@ -0,0 +1,138 @@
#include "StdAfx.h"
#include "Type.h"
#include "../EterLib/TextFileLoader.h"
std::string NSound::strResult;
const char* NSound::GetResultString()
{
return strResult.c_str();
}
void NSound::SetResultString(const char* c_pszStr)
{
strResult.assign(c_pszStr);
}
bool NSound::LoadSoundInformationPiece(const char* c_szFileName, NSound::TSoundDataVector& rSoundDataVector, const char* c_szPathHeader)
{
std::string strResult;
strResult = c_szFileName;
CTextFileLoader* pkTextFileLoader = CTextFileLoader::Cache(c_szFileName);
if (!pkTextFileLoader)
return false;
CTextFileLoader& rkTextFileLoader = *pkTextFileLoader;
if (rkTextFileLoader.IsEmpty())
{
SetResultString((strResult + " Can not open file for reading").c_str());
return false;
}
rkTextFileLoader.SetTop();
int iCount;
if (!rkTextFileLoader.GetTokenInteger("sounddatacount", &iCount))
{
SetResultString((strResult + " File format error, SoundDataCount Unable to find.").c_str());
return false;
}
rSoundDataVector.clear();
rSoundDataVector.resize(iCount);
char szSoundDataHeader[32 + 1];
for (uint32_t i = 0; i < rSoundDataVector.size(); ++i)
{
_snprintf_s(szSoundDataHeader, sizeof(szSoundDataHeader), "sounddata%02d", i);
CTokenVector* pTokenVector;
if (!rkTextFileLoader.GetTokenVector(szSoundDataHeader, &pTokenVector))
{
SetResultString((strResult + " File format error: " + szSoundDataHeader + " Unable to find").c_str());
return false;
}
if (2 != pTokenVector->size())
{
SetResultString((strResult + " File format error: The size of the vector is not 2").c_str());
return false;
}
rSoundDataVector[i].fTime = (float)atof(pTokenVector->at(0).c_str());
if (c_szPathHeader)
{
rSoundDataVector[i].strSoundFileName = c_szPathHeader;
rSoundDataVector[i].strSoundFileName += pTokenVector->at(1).c_str();
}
else
{
rSoundDataVector[i].strSoundFileName = pTokenVector->at(1).c_str();
}
//TraceError("LoadSoundInformation %s -- %f -- %s", c_szFileName, rSoundDataVector[i].fTime, rSoundDataVector[i].strSoundFileName.c_str());
}
SetResultString((strResult + " Loaded").c_str());
return true;
}
bool NSound::SaveSoundInformationPiece(const char* c_szFileName, NSound::TSoundDataVector& rSoundDataVector)
{
if (rSoundDataVector.empty()) // If no data is considered success
{
if (IsFile(c_szFileName)) // If the data is empty but there is a file
{
_unlink(c_szFileName); // erase.
}
return true;
}
std::string strResult;
strResult = c_szFileName;
FILE* File = fopen(c_szFileName, "wt");
if (!File)
{
char szErrorText[256 + 1];
_snprintf_s(szErrorText, sizeof(szErrorText), "Failed to save file (%s).\nPlease check if it is read-only or you have no space on the disk.\n", c_szFileName);
LogBox(szErrorText, "Error");
SetResultString((strResult + " Cannot open file for writing").c_str());
return false;
}
fprintf(File, "ScriptType CharacterSoundInformation\n");
fprintf(File, "\n");
fprintf(File, "SoundDataCount %llu\n", rSoundDataVector.size());
for (uint32_t i = 0; i < rSoundDataVector.size(); ++i)
{
NSound::TSoundData& rSoundData = rSoundDataVector[i];
fprintf(File, "SoundData%02d %f \"%s\"\n", i, rSoundData.fTime, rSoundData.strSoundFileName.c_str());
}
fclose(File);
return true;
}
void NSound::DataToInstance(const TSoundDataVector& c_rSoundDataVector, TSoundInstanceVector* pSoundInstanceVector)
{
if (c_rSoundDataVector.empty())
return;
uint32_t dwFPS = 60;
const float c_fFrameTime = 1.0f / float(dwFPS);
pSoundInstanceVector->clear();
pSoundInstanceVector->resize(c_rSoundDataVector.size());
for (uint32_t i = 0; i < c_rSoundDataVector.size(); ++i)
{
const TSoundData& c_rSoundData = c_rSoundDataVector[i];
TSoundInstance& rSoundInstance = pSoundInstanceVector->at(i);
rSoundInstance.dwFrame = (uint32_t)(c_rSoundData.fTime / c_fFrameTime);
rSoundInstance.strSoundFileName = c_rSoundData.strSoundFileName;
}
}

29
src/AudioLib/Type.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include <vector>
#include <string>
namespace NSound
{
extern std::string strResult;
typedef struct SSoundData
{
float fTime;
std::string strSoundFileName;
} TSoundData;
typedef struct SSoundInstance
{
uint32_t dwFrame;
std::string strSoundFileName;
} TSoundInstance;
typedef std::vector<TSoundData> TSoundDataVector;
typedef std::vector<TSoundInstance> TSoundInstanceVector;
bool LoadSoundInformationPiece(const char* c_szFileName, TSoundDataVector& rSoundDataVector, const char* c_szPathHeader = NULL);
bool SaveSoundInformationPiece(const char* c_szFileName, TSoundDataVector& rSoundDataVector);
void DataToInstance(const TSoundDataVector& c_rSoundDataVector, TSoundInstanceVector* pSoundInstanceVector);
const char* GetResultString();
void SetResultString(const char* c_pszStr);
};

View File

@@ -1,3 +1,4 @@
add_subdirectory(AudioLib)
add_subdirectory(Discord)
add_subdirectory(EffectLib)
add_subdirectory(EterBase)
@@ -8,7 +9,6 @@ add_subdirectory(EterLocale)
add_subdirectory(EterPack)
add_subdirectory(EterPythonLib)
add_subdirectory(GameLib)
add_subdirectory(MilesLib)
add_subdirectory(PRTerrainLib)
add_subdirectory(ScriptLib)
add_subdirectory(SpeedTreeLib)

View File

@@ -96,7 +96,7 @@ bool CEffectData::LoadScript(const char * c_szFileName)
bool CEffectData::LoadSoundScriptData(const char * c_szFileName)
{
TSoundDataVector SoundDataVector;
NSound::TSoundDataVector SoundDataVector;
if (LoadSoundInformationPiece(c_szFileName, SoundDataVector))
{
@@ -164,7 +164,7 @@ CEffectMeshScript * CEffectData::GetMeshPointer(DWORD dwPosition)
return m_MeshVector[dwPosition];
}
TSoundInstanceVector * CEffectData::GetSoundInstanceVector()
NSound::TSoundInstanceVector * CEffectData::GetSoundInstanceVector()
{
return &m_SoundInstanceVector;
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include "../milesLib/Type.h"
#include "../AudioLib/Type.h"
#include "ParticleSystemData.h"
#include "EffectMesh.h"
@@ -30,7 +30,7 @@ class CEffectData
DWORD GetLightCount();
CLightData * GetLightPointer(DWORD dwPosition);
TSoundInstanceVector * GetSoundInstanceVector();
NSound::TSoundInstanceVector * GetSoundInstanceVector();
float GetBoundingSphereRadius();
D3DXVECTOR3 GetBoundingSpherePosition();
@@ -52,7 +52,7 @@ class CEffectData
TParticleVector m_ParticleVector;
TMeshVector m_MeshVector;
TLightVector m_LightVector;
TSoundInstanceVector m_SoundInstanceVector;
NSound::TSoundInstanceVector m_SoundInstanceVector;
float m_fBoundingSphereRadius;
D3DXVECTOR3 m_v3BoundingSpherePosition;

View File

@@ -5,7 +5,7 @@
#include "../eterBase/Stl.h"
#include "../eterLib/StateManager.h"
#include "../MilesLib/SoundManager.h"
#include "../AudioLib/SoundEngine.h"
CDynamicPool<CEffectInstance> CEffectInstance::ms_kPool;
int CEffectInstance::ms_iRenderingEffectCount = 0;
@@ -50,12 +50,12 @@ void CEffectInstance::UpdateSound()
{
if (m_pSoundInstanceVector)
{
UpdateSoundInstance(m_dwFrame,
*m_pSoundInstanceVector,
m_matGlobal._41,
m_matGlobal._42,
m_matGlobal._43,
false);
SoundEngine::Instance().UpdateSoundInstance(m_matGlobal._41,
m_matGlobal._42,
m_matGlobal._43,
m_dwFrame,
m_pSoundInstanceVector,
false, false);
// NOTE : 매트릭스에서 위치를 직접 얻어온다 - [levites]
}
++m_dwFrame;

View File

@@ -2,7 +2,7 @@
#include "../eterlib/GrpObjectInstance.h"
#include "../eterlib/Pool.h"
#include "../mileslib/Type.h"
#include "../AudioLib/Type.h"
#include "EffectElementBaseInstance.h"
#include "EffectData.h"
@@ -77,7 +77,7 @@ class CEffectInstance : public CGraphicObjectInstance
std::vector<CEffectMeshInstance*> m_MeshInstanceVector;
std::vector<CLightInstance*> m_LightInstanceVector;
TSoundInstanceVector * m_pSoundInstanceVector;
NSound::TSoundInstanceVector * m_pSoundInstanceVector;
float m_fBoundingSphereRadius;
D3DXVECTOR3 m_v3BoundingSpherePosition;

View File

@@ -12,7 +12,7 @@
#include "../eterLib/StdAfx.h"
#include "../eterLib/TextFileLoader.h"
#include "../milesLib/StdAfx.h"
#include "../AudioLib/StdAfx.h"
/*
#include "FrameController.h"

View File

@@ -38,3 +38,9 @@ extern HWND g_PopupHwnd;
} \
#endif
#if defined(_DEBUG)
#define MD_ASSERT(expr) ((expr) ? true : (TraceError("MD_ASSERT('%s') failed at (%s:%d)", #expr, __FILE__, __LINE__), throw "ffs", false))
#else
#define MD_ASSERT(expr) ((expr) ? true : (TraceError("MD_ASSERT('%s') failed at (%s:%d)", #expr, __FILE__, __LINE__), false))
#endif

View File

@@ -1,16 +1,19 @@
#ifndef __INC_ETERPACKLIB_ETERPACK_H__
#define __INC_ETERPACKLIB_ETERPACK_H__
#ifndef MAKEFOURCC
#include <mmsyscom.h>
#endif
#include <list>
#include <unordered_map>
#include "EterBase/MappedFile.h"
//#define CHECKSUM_CHECK_MD5
#include "md5.h"
namespace eterpack
{
const DWORD c_PackCC = MAKEFOURCC('E', 'P', 'K', 'D');

View File

@@ -1,6 +1,6 @@
#include "StdAfx.h"
#include "../effectLib/EffectManager.h"
#include "../milesLib/SoundManager.h"
#include "../AudioLib/SoundEngine.h"
#include "ActorInstance.h"
#include "RaceData.h"

View File

@@ -1,6 +1,6 @@
#include "StdAfx.h"
#include "../EffectLib/EffectManager.h"
#include "../milesLib/SoundManager.h"
#include "../AudioLib/SoundEngine.h"
#include "ActorInstance.h"
#include "FlyingObjectManager.h"
@@ -29,9 +29,9 @@ void CActorInstance::SoundEventProcess(BOOL bCheckFrequency)
if (!m_pkCurRaceMotionData)
return;
const TSoundInstanceVector* c_pkVct_kSndInst = m_pkCurRaceMotionData->GetSoundInstanceVectorPointer();
UpdateSoundInstance(m_kCurMotNode.dwcurFrame, *c_pkVct_kSndInst,
m_x, m_y, m_z, bCheckFrequency);
const NSound::TSoundInstanceVector* c_pkVct_kSndInst = m_pkCurRaceMotionData->GetSoundInstanceVectorPointer();
SoundEngine::Instance().UpdateSoundInstance(m_x, m_y, m_z, m_kCurMotNode.dwcurFrame, c_pkVct_kSndInst,
bCheckFrequency, m_isMain);
}
void CActorInstance::MotionEventProcess(DWORD dwcurFrame, int iIndex, const CRaceMotionData::TMotionEventData * c_pData)
@@ -247,7 +247,7 @@ void CActorInstance::ProcessMotionEventSound(const CRaceMotionData::TMotionEvent
const CRaceMotionData::TMotionSoundEventData * c_pSoundData = (const CRaceMotionData::TMotionSoundEventData *)c_pData;
Tracenf("PLAY SOUND: %s", c_pSoundData->strSoundFileName.c_str());
CSoundManager::Instance().PlaySound3D(m_x, m_y, m_z, c_pSoundData->strSoundFileName.c_str());
SoundEngine::Instance().PlaySound3D(c_pSoundData->strSoundFileName.c_str(), m_x, m_y, m_z);
}
void CActorInstance::ProcessMotionEventFly(const CRaceMotionData::TMotionEventData * c_pData)

View File

@@ -1316,27 +1316,27 @@ void CArea::TAmbienceInstance::__Update(float fxCenter, float fyCenter, float fz
void CArea::TAmbienceInstance::UpdateOnceSound(float fxCenter, float fyCenter, float fzCenter)
{
float fDistance = sqrtf((fx - fxCenter)*(fx - fxCenter) + (fy - fyCenter)*(fy - fyCenter) + (fz - fzCenter)*(fz - fzCenter));
if (DWORD(fDistance) < dwRange)
if (uint32_t(fDistance) < dwRange)
{
if (!pSample)
if (!playSoundInstance)
{
if (AmbienceData.AmbienceSoundVector.empty())
return;
const char * c_szFileName = AmbienceData.AmbienceSoundVector[0].c_str();
pSample = CSoundManager::Instance().PlayAmbienceSound3D(fx, fy, fz, c_szFileName);
// Tracef(" %d : OncePlay [%f] : %s\n", iPlaySoundIndex, fDistance, c_szFileName);
const char* c_szFileName = AmbienceData.AmbienceSoundVector[0].c_str();
playSoundInstance = SoundEngine::Instance().PlayAmbienceSound3D(fx, fy, fz, c_szFileName);
}
}
else
else if (playSoundInstance)
{
pSample.reset();
playSoundInstance->Stop();
playSoundInstance = nullptr;
}
}
void CArea::TAmbienceInstance::UpdateStepSound(float fxCenter, float fyCenter, float fzCenter)
{
float fDistance = sqrtf((fx - fxCenter)*(fx - fxCenter) + (fy - fyCenter)*(fy - fyCenter) + (fz - fzCenter)*(fz - fzCenter));
float fDistance = sqrtf((fx - fxCenter) * (fx - fxCenter) + (fy - fyCenter) * (fy - fyCenter) + (fz - fzCenter) * (fz - fzCenter));
if (DWORD(fDistance) < dwRange)
{
float fcurTime = CTimer::Instance().GetCurrentSecond();
@@ -1346,9 +1346,8 @@ void CArea::TAmbienceInstance::UpdateStepSound(float fxCenter, float fyCenter, f
if (AmbienceData.AmbienceSoundVector.empty())
return;
const char * c_szFileName = AmbienceData.AmbienceSoundVector[0].c_str();
pSample = CSoundManager::Instance().PlayAmbienceSound3D(fx, fy, fz, c_szFileName);
// Tracef(" %d : StepPlay [%f] : %s\n", iPlaySoundIndex, fDistance, c_szFileName);
const char* c_szFileName = AmbienceData.AmbienceSoundVector[0].c_str();
playSoundInstance = SoundEngine::Instance().PlayAmbienceSound3D(fx, fy, fz, c_szFileName);
fNextPlayTime = CTimer::Instance().GetCurrentSecond();
fNextPlayTime += AmbienceData.fPlayInterval + frandom(0.0f, AmbienceData.fPlayIntervalVariation);
@@ -1356,7 +1355,7 @@ void CArea::TAmbienceInstance::UpdateStepSound(float fxCenter, float fyCenter, f
}
else
{
pSample.reset();
playSoundInstance = nullptr;
fNextPlayTime = 0.0f;
}
}
@@ -1364,20 +1363,24 @@ void CArea::TAmbienceInstance::UpdateStepSound(float fxCenter, float fyCenter, f
void CArea::TAmbienceInstance::UpdateLoopSound(float fxCenter, float fyCenter, float fzCenter)
{
float fDistance = sqrtf((fx - fxCenter) * (fx - fxCenter) + (fy - fyCenter) * (fy - fyCenter) + (fz - fzCenter) * (fz - fzCenter));
if (DWORD(fDistance) < dwRange)
if (uint32_t(fDistance) < dwRange)
{
if (!pSample)
if (!playSoundInstance)
{
pSample = CSoundManager::Instance().PlayAmbienceSound3D(fx, fy, fz, AmbienceData.AmbienceSoundVector[0], 0);
}
else
{
pSample->SetVolume(__GetVolumeFromDistance(fDistance));
if (AmbienceData.AmbienceSoundVector.empty())
return;
const char* c_szFileName = AmbienceData.AmbienceSoundVector[0].c_str();
playSoundInstance = SoundEngine::Instance().PlayAmbienceSound3D(fx, fy, fz, c_szFileName, 0);
}
if (playSoundInstance)
playSoundInstance->SetVolume(__GetVolumeFromDistance(fDistance));
}
else
else if (playSoundInstance)
{
pSample.reset();
playSoundInstance->Stop();
playSoundInstance = nullptr;
}
}

View File

@@ -68,7 +68,7 @@ class CArea
float fx, fy, fz;
DWORD dwRange;
float fMaxVolumeAreaPercentage;
std::unique_ptr<SoundSample> pSample;
MaSoundInstance* playSoundInstance;
float fNextPlayTime;
prt::TPropertyAmbience AmbienceData;

View File

@@ -4,7 +4,7 @@
class CProperty;
#include "../eterLib/SkyBox.h"
#include "../mileslib/SoundManager.h"
#include "../AudioLib/SoundEngine.h"
/////////////////////////////////////////////////////////////////
// Property

View File

@@ -295,7 +295,7 @@ float CRaceMotionData::GetEventStartTime(DWORD dwIndex) const
return m_MotionEventDataVector[dwIndex]->fStartingTime;
}
const TSoundInstanceVector * CRaceMotionData::GetSoundInstanceVectorPointer() const
const NSound::TSoundInstanceVector * CRaceMotionData::GetSoundInstanceVectorPointer() const
{
return &m_SoundInstanceVector;
}
@@ -553,7 +553,7 @@ bool CRaceMotionData::SaveMotionData(const char * c_szFileName)
#endif
bool CRaceMotionData::LoadSoundScriptData(const char * c_szFileName)
{
TSoundDataVector SoundDataVector;
NSound::TSoundDataVector SoundDataVector;
if (!LoadSoundInformationPiece(c_szFileName, SoundDataVector))
{
return false;

View File

@@ -1,6 +1,6 @@
#pragma once
#include "MilesLib/Type.h"
#include "AudioLib/Type.h"
#include "RaceMotionDataEvent.h"
class CRaceMotionData
@@ -253,7 +253,7 @@ class CRaceMotionData
float GetEventStartTime(DWORD dwIndex) const;
// Sound Data
const TSoundInstanceVector * GetSoundInstanceVectorPointer() const;
const NSound::TSoundInstanceVector * GetSoundInstanceVectorPointer() const;
// File
#ifdef WORLD_EDITOR
@@ -291,7 +291,7 @@ class CRaceMotionData
BOOL m_bCancelEnableSkill;
TMotionEventDataVector m_MotionEventDataVector;
TSoundInstanceVector m_SoundInstanceVector;
NSound::TSoundInstanceVector m_SoundInstanceVector;
private:
BOOL m_hasSplashEvent;

View File

@@ -23,7 +23,7 @@
#include "../eterBase/Random.h"
#include "../eterLib/StdAfx.h"
#include "../milesLib/StdAfx.h"
#include "../AudioLib/StdAfx.h"
#include "../effectLib/StdAfx.h"
#include "GameType.h"

View File

@@ -1,9 +0,0 @@
file(GLOB_RECURSE FILE_SOURCES "*.h" "*.c" "*.cpp")
add_library(MilesLib STATIC ${FILE_SOURCES})
target_link_libraries(MilesLib
lzo2
)
GroupSourcesByFolder(MilesLib)

View File

@@ -1,135 +0,0 @@
#include "Stdafx.h"
#include "MSSFileAPI.hpp"
#include "EterBase/Timer.h"
#include "EterBase/Utils.h"
#include "EterPack/StdAfx.h"
#include "EterPack/EterPackManager.h"
#include <mss.h>
#include <mutex>
#include <memory>
#include <algorithm>
#include <unordered_map>
namespace
{
enum ESeekType
{
SEEK_TYPE_BEGIN,
SEEK_TYPE_CURRENT,
SEEK_TYPE_END
};
struct CSeekPackFile
{
std::vector<uint8_t> packFile;
U32 seek_position;
~CSeekPackFile()
{
seek_position = 0;
}
U32 Seek(S32 offset, U32 type)
{
switch (type)
{
case SEEK_TYPE_BEGIN:
if (offset > packFile.size())
offset = packFile.size();
seek_position = offset;
break;
case SEEK_TYPE_CURRENT:
seek_position = MIN(seek_position + offset, packFile.size());
break;
case SEEK_TYPE_END:
seek_position = MAX(0, packFile.size() - offset);
break;
}
return seek_position;
}
BOOL Read(void* dest, int bytes)
{
if (seek_position + bytes > packFile.size())
return FALSE;
memcpy(dest, (const char*)packFile.data() + seek_position, bytes);
seek_position += bytes;
return TRUE;
}
};
static std::unordered_map<U32, CSeekPackFile> gs_SoundFile;
static std::vector<U32> gs_FreeIndexes;
static U32 gs_SoundFileIndex = 0;
static std::mutex gs_SoundFileMutex;
U32 AILCALLBACK open_callback(MSS_FILE const* filename, UINTa* file_handle)
{
std::lock_guard<std::mutex> lock(gs_SoundFileMutex);
U32 index = 0;
if (!gs_FreeIndexes.empty())
{
index = gs_FreeIndexes.back();
gs_FreeIndexes.pop_back();
}
else
{
index = ++gs_SoundFileIndex;
}
LPCVOID pData;
CMappedFile mappedFile;
if (!CEterPackManager::instance().Get(mappedFile, filename, &pData))
return 0;
gs_SoundFile[index].packFile.resize(mappedFile.Size());
memcpy(gs_SoundFile[index].packFile.data(), pData, mappedFile.Size());
*file_handle = index;
return 1;
}
void AILCALLBACK close_callback(UINTa file_handle)
{
std::lock_guard<std::mutex> l(gs_SoundFileMutex);
gs_SoundFile.erase(file_handle);
gs_FreeIndexes.push_back(file_handle);
}
S32 AILCALLBACK seek_callback(UINTa file_handle, S32 offset, U32 type)
{
auto it = gs_SoundFile.find(file_handle);
if (it == gs_SoundFile.end())
return 0;
return it->second.Seek(offset, type);
}
U32 AILCALLBACK read_callback(UINTa file_handle, void* buffer, U32 bytes)
{
auto it = gs_SoundFile.find(file_handle);
if (it == gs_SoundFile.end())
return 0;
DWORD dwRealSize = MIN(it->second.packFile.size(), bytes);
it->second.Read(buffer, dwRealSize);
return dwRealSize;
}
}
void RegisterMilesFileAPI()
{
AIL_set_file_callbacks(open_callback, close_callback,
seek_callback, read_callback);
}

View File

@@ -1,4 +0,0 @@
#pragma once
void RegisterMilesFileAPI();

View File

@@ -1,56 +0,0 @@
#include "Stdafx.h"
#include "MusicInstance.hpp"
MusicInstance::MusicInstance(HSTREAM stream, std::string_view filename,
float fVolume, float fVolumeSpeed)
: MusicState(MUSIC_STATE_FADE_IN)
, fVolume(fVolume)
, fLimitVolume(0.0f)
, fVolumeSpeed(fVolumeSpeed)
, filename(filename)
, stream(stream)
{
this->stream.SetVolume(fVolume);
this->stream.Play(0);
}
bool MusicInstance::Update(float musicVolume)
{
if (MUSIC_STATE_OFF == MusicState)
return false;
switch (MusicState)
{
case MUSIC_STATE_FADE_IN:
fVolume += fVolumeSpeed;
if (fVolume >= musicVolume)
{
fVolume = musicVolume;
fVolumeSpeed = 0.0f;
MusicState = MUSIC_STATE_PLAY;
}
stream.SetVolume(fVolume);
break;
case MUSIC_STATE_FADE_LIMIT_OUT:
fVolume -= fVolumeSpeed;
if (fVolume <= fLimitVolume)
{
fVolume = fLimitVolume;
fVolumeSpeed = 0.0f;
MusicState = MUSIC_STATE_OFF;
}
stream.SetVolume(fVolume);
break;
case MUSIC_STATE_FADE_OUT:
fVolume -= fVolumeSpeed;
return fVolume > 0.0f;
}
return true;
}

View File

@@ -1,30 +0,0 @@
#pragma once
#include <string_view>
#include "SoundStream.hpp"
#include <mss.h>
enum MusicState
{
MUSIC_STATE_OFF,
MUSIC_STATE_PLAY,
MUSIC_STATE_FADE_IN,
MUSIC_STATE_FADE_OUT,
MUSIC_STATE_FADE_LIMIT_OUT,
};
// TODO(tim): make members private?
struct MusicInstance
{
MusicInstance(HSTREAM stream, std::string_view filename,
float fVolume, float fVolumeSpeed);
bool Update(float musicVolume);
MusicState MusicState;
float fVolume;
float fLimitVolume;
float fVolumeSpeed;
std::string filename;
SoundStream stream;
};

View File

@@ -1,17 +0,0 @@
#include "Stdafx.h"
#include "SampleFile.hpp"
SampleFile::SampleFile(std::string_view filename, std::vector<uint8_t>&& data)
: m_filename(filename), fileData(std::forward<std::vector<uint8_t>>(data))
{
}
const void *SampleFile::GetData() const
{
return fileData.data();
}
uint32_t SampleFile::GetSize() const
{
return fileData.size();
}

View File

@@ -1,29 +0,0 @@
#pragma once
#include <memory>
#include "EterBase/StdAfx.h"
#include <string_view>
#include "EterPack/StdAfx.h"
#include "EterPack/EterPackmanager.h"
class SampleFile
{
public:
SampleFile(std::string_view filename, std::vector<uint8_t>&& data);
const std::string &GetFilename() const
{
return m_filename;
}
const void *GetData() const;
uint32_t GetSize() const;
private:
std::string m_filename;
std::vector<uint8_t> fileData;
};
using SampleFilePtr = std::shared_ptr<SampleFile>;

View File

@@ -1,31 +0,0 @@
#include "Stdafx.h"
#include "SampleFileCache.hpp"
#include "EterBase/Debug.h"
#include "EterLib/ResourceManager.h"
#include "EterPack/StdAfx.h"
#include "EterPack/EterPackManager.h"
SampleFilePtr SampleFileCache::Get(std::string_view filename)
{
const auto it = m_samples.find(filename);
if (it != m_samples.end())
return it->second;
LPCVOID pData;
CMappedFile mappedFile;
if(!CEterPackManager::instance().Get(mappedFile, filename.data(), &pData))
{
TraceError("Failed to open %s", filename);
return nullptr;
}
std::vector<uint8_t> fileData;
fileData.resize(mappedFile.Size());
memcpy(fileData.data(), pData, mappedFile.Size());
auto sample = std::make_shared<SampleFile>(filename, std::move(fileData));
m_samples.emplace(sample->GetFilename(), sample);
return sample;
}

View File

@@ -1,15 +0,0 @@
#pragma once
#include "SampleFile.hpp"
#include <unordered_map>
class SampleFileCache
{
public:
SampleFilePtr Get(std::string_view filename);
private:
std::unordered_map<std::string_view, SampleFilePtr> m_samples;
};

View File

@@ -1,393 +0,0 @@
#include "StdAfx.h"
#include "SoundManager.h"
#include "EterBase/Timer.h"
#include "EterBase/Utils.h"
#include "EterBase/Debug.h"
#undef min
#undef max
#include <cmath>
//#define IS_STATIC
//#include <StepTimer.h>
#include "MSSFileAPI.hpp"
#include <mss.h>
MilesLibrary::MilesLibrary()
{
Register_RIB(MP3Dec);
//AIL_configure_logging("miles.log", nullptr, 2);
AIL_startup();
RegisterMilesFileAPI();
}
MilesLibrary::~MilesLibrary()
{
AIL_shutdown();
}
CSoundManager::CSoundManager()
: m_isSoundDisable(false), m_max2dSoundsPlaying(8), m_max3dSoundsPlaying(64), m_maxMusicPlaying(4),
m_fxPosition(0.0f), m_fyPosition(0.0f), m_fzPosition(0.0f), m_fSoundScale(200.0f), m_fAmbienceSoundScale(1000.0f),
m_fSoundVolume(1.0f), m_fMusicVolume(1.0f), m_fBackupMusicVolume(0.0f), m_fBackupSoundVolume(0.0f),
m_driver(nullptr)
{
// ctor
}
bool CSoundManager::Create()
{
m_driver = AIL_open_digital_driver(44100, 16, MSS_MC_USE_SYSTEM_CONFIG , 0);
if (!m_driver)
{
Tracenf("AIL_open_digital_driver(): %s", AIL_last_error());
return false;
}
AIL_set_3D_distance_factor(m_driver, 0.001f);
return true;
}
void CSoundManager::SetPosition(float fx, float fy, float fz)
{
m_fxPosition = fx;
m_fyPosition = fy;
m_fzPosition = fz;
}
void CSoundManager::SetDirection(float fxDir, float fyDir, float fzDir, float fxUp, float fyUp, float fzUp)
{
if (!m_driver)
return;
AIL_set_listener_3D_orientation(m_driver, fxDir, fyDir, -fzDir, fxUp, fyUp, -fzUp);
}
void CSoundManager::Update()
{
for (auto it = m_sounds2d.begin(); it != m_sounds2d.end();)
{
if (it->IsDone())
it = m_sounds2d.erase(it);
else
++it;
}
for (auto it = m_sounds3d.begin(); it != m_sounds3d.end();)
{
if (it->IsDone())
it = m_sounds3d.erase(it);
else
++it;
}
for (auto it = m_music.begin(); it != m_music.end();)
{
// If Update() returns false, the song has finished playing.
if (it->second.Update(m_fMusicVolume))
++it;
else
it = m_music.erase(it);
}
}
float CSoundManager::GetSoundScale()
{
return m_fSoundScale;
}
void CSoundManager::SetSoundScale(float fScale)
{
m_fSoundScale = fScale;
}
void CSoundManager::SetAmbienceSoundScale(float fScale)
{
m_fAmbienceSoundScale = fScale;
}
void CSoundManager::SetSoundVolume(float fVolume)
{
if (m_isSoundDisable)
{
m_fBackupSoundVolume = fVolume;
return;
}
fVolume = std::max(std::min(fVolume, 1.0f), 0.0f);
m_fSoundVolume = fVolume;
m_fBackupSoundVolume = fVolume;
}
void CSoundManager::SetMusicVolume(float fVolume)
{
if (m_isSoundDisable)
{
m_fBackupMusicVolume = fVolume;
return;
}
fVolume = std::max(std::min(fVolume, 1.0f), 0.0f);
m_fMusicVolume = fVolume;
m_fBackupMusicVolume = fVolume;
for (auto &p : m_music)
{
if (MUSIC_STATE_OFF == p.second.MusicState)
continue;
if (MUSIC_STATE_FADE_OUT == p.second.MusicState)
continue;
p.second.fVolume = fVolume;
p.second.stream.SetVolume(fVolume);
}
}
void CSoundManager::SaveVolume()
{
// NOTE : 두번 이상 Save를 시도할때는 그냥 Return
if (m_isSoundDisable)
return;
float fBackupMusicVolume = m_fMusicVolume;
float fBackupSoundVolume = m_fSoundVolume;
SetMusicVolume(0.0f);
SetSoundVolume(0.0f);
m_fBackupMusicVolume = fBackupMusicVolume;
m_fBackupSoundVolume = fBackupSoundVolume;
m_isSoundDisable = true;
}
void CSoundManager::RestoreVolume()
{
m_isSoundDisable = false;
SetMusicVolume(m_fBackupMusicVolume);
SetSoundVolume(m_fBackupSoundVolume);
}
float CSoundManager::GetSoundVolume()
{
return m_fSoundVolume;
}
float CSoundManager::GetMusicVolume()
{
return m_fMusicVolume;
}
void CSoundManager::PlaySound2D(std::string_view filename)
{
if (0.0f == GetSoundVolume())
return;
if (m_sounds2d.size() >= m_max2dSoundsPlaying)
return;
const auto file = m_cache.Get(filename);
if (!file)
return;
if (!m_driver)
return;
const auto sample = AIL_allocate_sample_handle(m_driver);
if (!sample)
{
Tracenf("AIL_allocate_sample_handle(): %s for %s", AIL_last_error(), filename.data());
return;
}
m_sounds2d.emplace_back(sample);
m_sounds2d.back().SetFile(file);
m_sounds2d.back().SetVolume(GetSoundVolume());
m_sounds2d.back().Play(1);
}
float CSoundManager::__GetVolumeFromDistance(float fDistance)
{
return GetSoundVolume() - (fDistance / 2500);
}
// return 1.0f / (1.0f + (1.0f * (fDistance - 1.0f)));
void CSoundManager::PlaySound3D(float fx, float fy, float fz, std::string_view filename, int iPlayCount)
{
if (0.0f == GetSoundVolume())
return;
if (m_sounds3d.size() >= m_max3dSoundsPlaying)
{
return;
}
const auto file = m_cache.Get(filename);
if (!file)
{
Tracenf("Not playing %s file not found", filename.data());
return;
}
const auto sample = AIL_allocate_sample_handle(m_driver);
if (!sample)
{
Tracenf("AIL_allocate_sample_handle(): %s for %s", AIL_last_error(), filename.data());
return;
}
float fDistance = sqrtf((fx - m_fxPosition) * (fx - m_fxPosition) + (fy - m_fyPosition) * (fy - m_fyPosition) +
(fz - m_fzPosition) * (fz - m_fzPosition));
Tracenf("SampSet distance {} {}", fDistance ,__GetVolumeFromDistance(fDistance));
m_sounds3d.emplace_back(sample);
m_sounds3d.back().SetFile(file);
m_sounds3d.back().SetPosition((fx - m_fxPosition) / m_fSoundScale,
(fy - m_fyPosition) / m_fSoundScale,
(fz - m_fzPosition) / m_fSoundScale);
m_sounds3d.back().SetVolume(__GetVolumeFromDistance(fDistance));
m_sounds3d.back().Play(iPlayCount);
}
std::unique_ptr<SoundSample> CSoundManager::PlayAmbienceSound3D(float fx, float fy, float fz, std::string_view filename,
int iPlayCount)
{
if (0.0f == GetSoundVolume())
return nullptr;
if (m_sounds3d.size() >= m_max3dSoundsPlaying)
return nullptr;
const auto file = m_cache.Get(filename);
if (!file)
return nullptr;
if (!m_driver)
return nullptr;
const auto sample = AIL_allocate_sample_handle(m_driver);
if (!sample)
{
Tracenf("AIL_allocate_sample_handle(): %s for %s", AIL_last_error(), filename.data());
return nullptr;
}
auto sound = std::make_unique<SoundSample>(sample);
sound->SetFile(file);
sound->SetPosition((fx - m_fxPosition) / m_fSoundScale,
(fy - m_fyPosition) / m_fSoundScale,
(fz - m_fzPosition) / m_fSoundScale);
sound->SetVolume(GetSoundVolume());
sound->Play(iPlayCount);
return sound;
}
void CSoundManager::PlayCharacterSound3D(float fx, float fy, float fz, const std::string &filename,
bool bCheckFrequency)
{
if (0.0f == GetSoundVolume())
return;
// 어느 정도의 최적화가 필요할 수도 있다 - [levites]
if (bCheckFrequency)
{
static float s_fLimitDistance = 5000 * 5000;
float fdx = (fx - m_fxPosition) * (fx - m_fxPosition);
float fdy = (fy - m_fyPosition) * (fy - m_fyPosition);
if (fdx + fdy > s_fLimitDistance)
return;
const auto itor = m_playSoundHistoryMap.find(filename);
if (m_playSoundHistoryMap.end() != itor)
{
float fTime = itor->second;
if (CTimer::instance().GetCurrentSecond() - fTime < 0.3f)
//if (DX::StepTimer::instance().GetTotalSeconds() - fTime < 0.3f)
{
// Tracef("똑같은 소리가 0.3초 내에 다시 플레이 %s\n", filename);
return;
}
m_playSoundHistoryMap.erase(itor);
}
m_playSoundHistoryMap.emplace(filename, CTimer::instance().GetCurrentSecond());
//m_playSoundHistoryMap.emplace(filename, DX::StepTimer::instance().GetTotalSeconds());
}
Tracenf("Playing sound %s", filename.data());
PlaySound3D(fx, fy, fz, filename, 1);
}
void CSoundManager::StopAllSound3D()
{
m_sounds3d.clear();
}
void CSoundManager::FadeInMusic(const std::string &filename, float fVolumeSpeed)
{
const auto it = m_music.find(filename);
if (it != m_music.end())
{
it->second.MusicState = MUSIC_STATE_FADE_IN;
it->second.fVolumeSpeed = fVolumeSpeed;
return;
}
if (m_music.size() >= m_maxMusicPlaying)
return;
FadeOutAllMusic();
if (!m_driver)
return;
const auto stream = AIL_open_stream(m_driver, filename.c_str(), 0);
if (!stream)
{
Tracenf("AIL_open_stream(%s): %s", filename.c_str(), AIL_last_error());
return;
}
m_music.emplace(std::piecewise_construct, std::forward_as_tuple(filename),
std::forward_as_tuple(stream, filename, 0.0f, fVolumeSpeed));
}
void CSoundManager::FadeLimitOutMusic(const std::string &filename, float fLimitVolume, float fVolumeSpeed)
{
const auto it = m_music.find(filename);
if (it == m_music.end())
{
Tracenf("FadeLimitOutMusic: %s is not being played", filename.c_str());
return;
}
it->second.MusicState = MUSIC_STATE_FADE_LIMIT_OUT;
it->second.fVolumeSpeed = fVolumeSpeed;
it->second.fLimitVolume = fLimitVolume;
}
void CSoundManager::FadeOutMusic(const std::string &filename, float fVolumeSpeed)
{
const auto it = m_music.find(filename);
if (it == m_music.end())
{
Tracenf("FadeOutMusic: %s is not being played", filename.c_str());
return;
}
it->second.MusicState = MUSIC_STATE_FADE_OUT;
it->second.fVolumeSpeed = fVolumeSpeed;
}
void CSoundManager::FadeOutAllMusic()
{
for (auto &p : m_music)
{
if (MUSIC_STATE_OFF == p.second.MusicState)
continue;
p.second.MusicState = MUSIC_STATE_FADE_OUT;
p.second.fVolumeSpeed = 0.01f;
}
}

View File

@@ -1,90 +0,0 @@
#pragma once
#include "EterBase/Singleton.h"
#include "SampleFileCache.hpp"
#include "MusicInstance.hpp"
#include "SoundSample.hpp"
#include <unordered_map>
struct MilesLibrary
{
MilesLibrary();
~MilesLibrary();
};
class CSoundManager : public CSingleton<CSoundManager>
{
public:
CSoundManager();
bool Create();
void SetPosition(float fx, float fy, float fz);
void SetDirection(float fxDir, float fyDir, float fzDir, float fxUp, float fyUp, float fzUp);
void Update();
float GetSoundScale();
void SetSoundScale(float fScale);
void SetAmbienceSoundScale(float fScale);
void SetSoundVolume(float fVolume);
void SetMusicVolume(float fVolume);
void SaveVolume();
void RestoreVolume();
float GetSoundVolume();
float GetMusicVolume();
// Sound
void PlaySound2D(std::string_view filename);
float __GetVolumeFromDistance(float fDistance);
void PlaySound3D(float fx, float fy, float fz,
std::string_view filename,
int iPlayCount = 1);
std::unique_ptr<SoundSample> PlayAmbienceSound3D(float fx, float fy, float fz,
std::string_view filename,
int iPlayCount = 1);
void PlayCharacterSound3D(float fx, float fy, float fz,
const std::string &filename,
bool bCheckFrequency = false);
void StopAllSound3D();
// Music
void FadeInMusic(const std::string &filename,
float fVolumeSpeed = 0.016f);
void FadeOutMusic(const std::string &filename,
float fVolumeSpeed = 0.016f);
void FadeLimitOutMusic(const std::string &filename,
float fLimitVolume, float fVolumeSpeed = 0.016f);
void FadeOutAllMusic();
protected:
MilesLibrary m_miles;
bool m_isSoundDisable;
uint32_t m_max2dSoundsPlaying;
uint32_t m_max3dSoundsPlaying;
uint32_t m_maxMusicPlaying;
float m_fxPosition;
float m_fyPosition;
float m_fzPosition;
float m_fSoundScale;
float m_fAmbienceSoundScale;
float m_fSoundVolume;
float m_fMusicVolume;
float m_fBackupMusicVolume;
float m_fBackupSoundVolume;
HDIGDRIVER m_driver;
SampleFileCache m_cache;
std::unordered_map<std::string, MusicInstance> m_music;
std::vector<SoundSample> m_sounds2d;
std::vector<SoundSample> m_sounds3d;
std::unordered_map<std::string, float> m_playSoundHistoryMap;
};

View File

@@ -1,108 +0,0 @@
#include "Stdafx.h"
#include "SoundSample.hpp"
#include "../EterBase/Debug.h"
#include "../EterBase/Timer.h"
#include "../EterBase/Utils.h"
SoundSample::SoundSample(HSAMPLE sample) : m_sample(sample)
{
}
SoundSample::SoundSample(SoundSample &&other) : m_sample(other.m_sample), m_sampleFile(std::move(other.m_sampleFile))
{
other.m_sample = nullptr;
other.m_sampleFile.reset();
}
SoundSample::~SoundSample()
{
if (m_sample)
{
AIL_release_sample_handle(m_sample);
m_sample = nullptr;
}
}
SoundSample &SoundSample::operator=(SoundSample &&other)
{
if (this == &other)
return *this;
if (m_sample)
AIL_release_sample_handle(m_sample);
m_sample = other.m_sample;
other.m_sample = nullptr;
m_sampleFile = std::move(other.m_sampleFile);
return *this;
}
bool SoundSample::SetFile(SampleFilePtr sample)
{
if (!AIL_set_named_sample_file(m_sample, sample->GetFilename().c_str(), sample->GetData(), sample->GetSize(), 0))
{
Tracenf("%s: %s", sample->GetFilename().c_str(), AIL_last_error());
return false;
}
m_sampleFile = std::move(sample);
return true;
}
bool SoundSample::IsDone() const
{
return AIL_sample_status(m_sample) == SMP_DONE;
}
void SoundSample::Play(int loopCount) const
{
//AIL_set_sample_3D_distances(m_sample, 5000.0f, -1.0f, 0);
AIL_set_sample_loop_count(m_sample, loopCount);
AIL_start_sample(m_sample);
}
void SoundSample::Pause() const
{
AIL_stop_sample(m_sample);
}
void SoundSample::Resume() const
{
AIL_resume_sample(m_sample);
}
void SoundSample::Stop() const
{
AIL_end_sample(m_sample);
}
float SoundSample::GetVolume() const
{
float volume;
AIL_sample_volume_pan(m_sample, &volume, nullptr);
return volume;
}
void SoundSample::SetVolume(float volume) const
{
volume = std::max<float>(0.0f, std::min<float>(1.0f, volume));
AIL_set_sample_volume_pan(m_sample, volume, 0.5f);
}
void SoundSample::SetPosition(float x, float y, float z) const
{
//AIL_set_sample_3D_position(m_sample, x, y, -z);
// AIL_set_sample_is_3D(m_sample, FALSE);
}
void SoundSample::SetVelocity(float fDistanceX, float fDistanceY, float fDistanceZ, float fNagnitude) const
{
AIL_set_sample_3D_velocity(m_sample, fDistanceX, fDistanceY, fDistanceZ, fNagnitude);
}
void SoundSample::UpdatePosition(float fElapsedTime)
{
AIL_update_sample_3D_position(m_sample, fElapsedTime);
}

View File

@@ -1,35 +0,0 @@
#pragma once
#include "SampleFile.hpp"
#include <mss.h>
class SoundSample
{
public:
SoundSample(HSAMPLE sample);
SoundSample(SoundSample &&other);
SoundSample(const SoundSample &other) = delete;
~SoundSample();
SoundSample &operator=(SoundSample &&other);
SoundSample &operator=(const SoundSample &other) = delete;
bool SetFile(SampleFilePtr sample);
void Play(int loopCount = 1) const;
void Pause() const;
void Resume() const;
void Stop() const;
float GetVolume() const;
void SetVolume(float volume) const;
bool IsDone() const;
void SetPosition(float x, float y, float z) const;
void SetVelocity(float fx, float fy, float fz, float fMagnitude) const;
void UpdatePosition(float fElapsedTime);
private:
HSAMPLE m_sample;
SampleFilePtr m_sampleFile;
};

View File

@@ -1,66 +0,0 @@
#include "Stdafx.h"
#include "SoundStream.hpp"
#include <algorithm>
SoundStream::SoundStream(HSTREAM stream)
: m_stream(stream)
{
}
SoundStream::~SoundStream()
{
if (m_stream)
{
AIL_close_stream(m_stream);
m_stream = nullptr;
}
}
bool SoundStream::IsDone() const
{
return AIL_stream_status(m_stream) == -1;
}
void SoundStream::Play(int loopCount) const
{
AIL_set_stream_loop_count(m_stream, loopCount);
AIL_start_stream(m_stream);
}
void SoundStream::Pause() const
{
AIL_pause_stream(m_stream, 1);
}
void SoundStream::Resume() const
{
AIL_pause_stream(m_stream, 0);
}
void SoundStream::Stop()
{
AIL_close_stream(m_stream);
m_stream = NULL;
}
float SoundStream::GetVolume() const
{
const auto sample = AIL_stream_sample_handle(m_stream);
if (!sample)
return 0.0f;
F32 volume;
AIL_sample_volume_pan(sample, &volume, nullptr);
return volume;
}
void SoundStream::SetVolume(float volume) const
{
const auto sample = AIL_stream_sample_handle(m_stream);
if (!sample)
return;
volume = std::max<float>(0.0f, std::min<float>(1.0f, volume));
AIL_set_sample_volume_pan(sample, volume, 0.5f);
}

View File

@@ -1,25 +0,0 @@
#pragma once
#include <mss.h>
class SoundStream
{
public:
SoundStream(HSTREAM stream);
~SoundStream();
SoundStream(const SoundStream&) = delete;
void operator=(const SoundStream&) = delete;
void Play(int loopCount = 1) const;
void Pause() const;
void Resume() const;
void Stop();
float GetVolume() const;
void SetVolume(float volume) const;
bool IsDone() const;
private:
HSTREAM m_stream;
};

View File

@@ -1,5 +0,0 @@
#pragma once
#include "EterBase/StdAfx.h"
#include <mss.h>

View File

@@ -1,150 +0,0 @@
#include "Stdafx.h"
#include "Type.h"
#include "SoundManager.h"
#include "../EterBase/Debug.h"
#include "../EterLib/TextFileLoader.h"
#include "../EterLib/Util.h"
bool LoadSoundInformationPiece(const char *c_szFileName,
TSoundDataVector &rSoundDataVector,
const char *c_szPathHeader)
{
CTextFileLoader *pkTextFileLoader = CTextFileLoader::Cache(c_szFileName);
if (!pkTextFileLoader)
return false;
CTextFileLoader &rkTextFileLoader = *pkTextFileLoader;
if (rkTextFileLoader.IsEmpty())
return false;
rkTextFileLoader.SetTop();
int iCount;
if (!rkTextFileLoader.GetTokenInteger("sounddatacount", &iCount))
{
Tracenf("%s: no SoundDataCount", c_szFileName);
return false;
}
rSoundDataVector.clear();
rSoundDataVector.resize(iCount);
char szSoundDataHeader[32 + 1];
for (uint32_t i = 0; i < rSoundDataVector.size(); ++i)
{
_snprintf(szSoundDataHeader, sizeof(szSoundDataHeader), "sounddata%02d", i);
CTokenVector *pTokenVector;
if (!rkTextFileLoader.GetTokenVector(szSoundDataHeader, &pTokenVector))
{
Tracenf("%s: no %s", c_szFileName, szSoundDataHeader);
return false;
}
if (2 != pTokenVector->size())
{
Tracenf("%s: %s has wrong size %u", c_szFileName,
szSoundDataHeader, pTokenVector->size());
return false;
}
rSoundDataVector[i].fTime = (float)atof(pTokenVector->at(0).c_str());
if (c_szPathHeader)
{
rSoundDataVector[i].strSoundFileName = c_szPathHeader;
rSoundDataVector[i].strSoundFileName += pTokenVector->at(1).c_str();
}
else
{
rSoundDataVector[i].strSoundFileName = pTokenVector->at(1).c_str();
}
}
return true;
}
bool SaveSoundInformationPiece(const char *c_szFileName, TSoundDataVector &rSoundDataVector)
{
/*storm::String realFilename;
GetVfs().GetPathTranslator().Translate(c_szFileName, realFilename);
if (rSoundDataVector.empty()) // 데이터가 없으면 성공으로 간주
{
::DeleteFileA(realFilename.c_str());
return true;
}
storm::File File;
bsys::error_code ec;
File.Open(realFilename, ec,
storm::AccessMode::kWrite,
storm::CreationDisposition::kCreateAlways,
storm::ShareMode::kNone,
storm::UsageHint::kSequential);
if (ec) {
SPDLOG_ERROR("Failed to open {0} for writing with {1}",
realFilename, ec);
return false;
}
PrintfTabs(File, 0, "ScriptType CharacterSoundInformation\n");
PrintfTabs(File, 0, "\n");
PrintfTabs(File, 0, "SoundDataCount %d\n", rSoundDataVector.size());
for (uint32_t i = 0; i < rSoundDataVector.size(); ++i)
{
const auto & rSoundData = rSoundDataVector[i];
PrintfTabs(File, 0, "SoundData%02d %f \"%s\"\n",
i, rSoundData.fTime,
rSoundData.strSoundFileName.c_str());
}
*/
return true;
}
void DataToInstance(const TSoundDataVector &c_rSoundDataVector, TSoundInstanceVector *pSoundInstanceVector)
{
if (c_rSoundDataVector.empty())
return;
const float c_fFrameTime = 1.0f / 60.0f;
pSoundInstanceVector->clear();
pSoundInstanceVector->resize(c_rSoundDataVector.size());
for (uint32_t i = 0; i < c_rSoundDataVector.size(); ++i)
{
const TSoundData &c_rSoundData = c_rSoundDataVector[i];
TSoundInstance &rSoundInstance = pSoundInstanceVector->at(i);
rSoundInstance.dwFrame = (uint32_t)(c_rSoundData.fTime / c_fFrameTime);
rSoundInstance.strSoundFileName = c_rSoundData.strSoundFileName;
}
}
void UpdateSoundInstance(uint32_t frame, const TSoundInstanceVector &sounds,
float fx, float fy, float fz, bool bCheckFrequency)
{
auto &snd = CSoundManager::Instance();
for (const auto &instance : sounds)
{
if (instance.dwFrame != frame)
continue;
snd.PlayCharacterSound3D(fx, fy, fz,
instance.strSoundFileName,
bCheckFrequency);
}
}
void UpdateSoundInstance(uint32_t frame, const TSoundInstanceVector &sounds)
{
for (const auto &instance : sounds)
{
if (instance.dwFrame == frame)
CSoundManager::Instance().PlaySound2D(instance.strSoundFileName);
}
}

View File

@@ -1,37 +0,0 @@
#ifndef METIN2_CLIENT_MILESLIB_TYPE_HPP
#define METIN2_CLIENT_MILESLIB_TYPE_HPP
#pragma once
#include <vector>
typedef struct SSoundData
{
float fTime;
std::string strSoundFileName;
} TSoundData;
typedef struct SSoundInstance
{
uint32_t dwFrame;
std::string strSoundFileName;
} TSoundInstance;
typedef std::vector<TSoundData> TSoundDataVector;
typedef std::vector<TSoundInstance> TSoundInstanceVector;
bool LoadSoundInformationPiece(const char *c_szFileName,
TSoundDataVector &rSoundDataVector,
const char *c_szPathHeader = NULL);
bool SaveSoundInformationPiece(const char *c_szFileName,
TSoundDataVector &rSoundDataVector);
void DataToInstance(const TSoundDataVector &c_rSoundDataVector,
TSoundInstanceVector *pSoundInstanceVector);
void UpdateSoundInstance(uint32_t frame, const TSoundInstanceVector &sounds,
float fx, float fy, float fz, bool bCheckFrequency);
void UpdateSoundInstance(uint32_t frame, const TSoundInstanceVector &sounds);
#endif

View File

@@ -9,6 +9,7 @@ set_target_properties(UserInterface PROPERTIES LINK_FLAGS "/level='requireAdmini
)
target_link_libraries(UserInterface
AudioLib
Discord
EffectLib
EterBase
@@ -19,7 +20,6 @@ target_link_libraries(UserInterface
EterPack
EterPythonLib
GameLib
MilesLib
PRTerrainLib
ScriptLib
SpeedTreeLib
@@ -31,7 +31,6 @@ target_link_libraries(UserInterface
DirectX
Granny
SpeedTree
MilesSoundSystem
Python
WebView

View File

@@ -1051,10 +1051,10 @@ bool CPythonApplication::Create(PyObject * poSelf, const char * c_szName, int wi
if (!m_pySystem.IsNoSoundCard())
{
// Sound
if (!m_SoundManager.Create())
if (!m_SoundEngine.Initialize())
{
// NOTE : Áß±¹ÃøÀÇ ¿äûÀ¸·Î »ý·«
// LogBox(ApplicationStringTable_GetStringz(IDS_WARN_NO_SOUND_DEVICE));
TraceError("Failed to initialize sound manager!");
return false; // Is this important enough to stop the client?
}
}

View File

@@ -11,7 +11,7 @@
#include "gamelib/ItemManager.h"
#include "gamelib/FlyingObjectManager.h"
#include "gamelib/GameEventManager.h"
#include "milesLib/SoundManager.h"
#include "AudioLib/SoundEngine.h"
#include "PythonEventManager.h"
#include "PythonPlayer.h"
@@ -310,7 +310,7 @@ class CPythonApplication : public CMSApplication, public CInputKeyboard, public
CTimer m_timer;
CLightManager m_LightManager;
CSoundManager m_SoundManager;
SoundEngine m_SoundEngine;
CFlyingManager m_FlyingManager;
CRaceManager m_RaceManager;
CGameEventManager m_GameEventManager;

View File

@@ -91,9 +91,9 @@ void CPythonApplication::__UpdateCamera()
// Sound Setting
const D3DXVECTOR3 & c_rv3CameraDirection = pMainCamera->GetView();
const D3DXVECTOR3 & c_rv3CameraUp = pMainCamera->GetUp();
m_SoundManager.SetPosition(m_v3CenterPosition.x, m_v3CenterPosition.y, m_v3CenterPosition.z); // Listener - 캐릭터 위치
m_SoundManager.SetDirection(c_rv3CameraDirection.x, c_rv3CameraDirection.y, c_rv3CameraDirection.z, c_rv3CameraUp.x, c_rv3CameraUp.y, c_rv3CameraUp.z);
m_SoundManager.Update();
m_SoundEngine.SetListenerPosition(m_v3CenterPosition.x, m_v3CenterPosition.y, m_v3CenterPosition.z); // Listener - 캐릭터 위치
m_SoundEngine.SetListenerOrientation(c_rv3CameraDirection.x, c_rv3CameraDirection.y, c_rv3CameraDirection.z, c_rv3CameraUp.x, c_rv3CameraUp.y, c_rv3CameraUp.z);
m_SoundEngine.Update();
//////////////////////
}

View File

@@ -60,7 +60,7 @@ LRESULT CPythonApplication::WindowProcedure(HWND hWnd, UINT uiMsg, WPARAM wParam
if (m_isActivateWnd)
{
m_SoundManager.RestoreVolume();
m_SoundEngine.RestoreVolume();
//////////////////
@@ -71,7 +71,7 @@ LRESULT CPythonApplication::WindowProcedure(HWND hWnd, UINT uiMsg, WPARAM wParam
}
else
{
m_SoundManager.SaveVolume();
m_SoundEngine.SaveVolume(m_isMinimizedWnd);
//////////////////

View File

@@ -32,7 +32,7 @@ void CPythonItem::TGroundItemInstance::__PlayDropSound(DWORD eItemType, const D3
if (eItemType>=DROPSOUND_NUM)
return;
CSoundManager::Instance().PlaySound3D(c_rv3Pos.x, c_rv3Pos.y, c_rv3Pos.z, ms_astDropSoundFileName[eItemType].c_str());
SoundEngine::Instance().PlaySound3D(ms_astDropSoundFileName[eItemType].c_str(), c_rv3Pos.x, c_rv3Pos.y, c_rv3Pos.z);
}
bool CPythonItem::TGroundItemInstance::Update()
@@ -165,7 +165,7 @@ void CPythonItem::PlayUseSound(DWORD dwItemID)
if (eItemType>=USESOUND_NUM)
return;
CSoundManager::Instance().PlaySound2D(m_astUseSoundFileName[eItemType].c_str());
SoundEngine::Instance().PlaySound2D(m_astUseSoundFileName[eItemType].c_str());
}
@@ -181,12 +181,12 @@ void CPythonItem::PlayDropSound(DWORD dwItemID)
if (eItemType>=DROPSOUND_NUM)
return;
CSoundManager::Instance().PlaySound2D(SGroundItemInstance::ms_astDropSoundFileName[eItemType].c_str());
SoundEngine::Instance().PlaySound2D(SGroundItemInstance::ms_astDropSoundFileName[eItemType].c_str());
}
void CPythonItem::PlayUsePotionSound()
{
CSoundManager::Instance().PlaySound2D(m_astUseSoundFileName[USESOUND_POTION].c_str());
SoundEngine::Instance().PlaySound2D(m_astUseSoundFileName[USESOUND_POTION].c_str());
}
DWORD CPythonItem::__GetDropSoundType(const CItemData& c_rkItemData)

View File

@@ -1,18 +1,17 @@
#include "StdAfx.h"
#include "PythonApplication.h"
PyObject * sndPlaySound(PyObject * poSelf, PyObject * poArgs)
PyObject* sndPlaySound2D(PyObject* poSelf, PyObject* poArgs)
{
char * szFileName;
char* szFileName;
if (!PyTuple_GetString(poArgs, 0, &szFileName))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.PlaySound2D(szFileName);
SoundEngine::Instance().PlaySound2D(szFileName);
return Py_BuildNone();
}
PyObject * sndPlaySound3D(PyObject * poSelf, PyObject * poArgs)
PyObject* sndPlaySound3D(PyObject* poSelf, PyObject* poArgs)
{
float fx;
if (!PyTuple_GetFloat(poArgs, 0, &fx))
@@ -23,58 +22,43 @@ PyObject * sndPlaySound3D(PyObject * poSelf, PyObject * poArgs)
float fz;
if (!PyTuple_GetFloat(poArgs, 2, &fz))
return Py_BuildException();
char * szFileName;
char* szFileName;
if (!PyTuple_GetString(poArgs, 3, &szFileName))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.PlaySound3D(fx, fy, fz, szFileName);
SoundEngine::Instance().PlaySound3D(szFileName, fx, fy, fz);
return Py_BuildNone();
}
PyObject * sndPlayMusic(PyObject * poSelf, PyObject * poArgs)
PyObject* sndFadeInMusic(PyObject* poSelf, PyObject* poArgs)
{
char * szFileName;
char* szFileName;
if (!PyTuple_GetString(poArgs, 0, &szFileName))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.PlaySound2D(szFileName);
SoundEngine::Instance().FadeInMusic(szFileName);
return Py_BuildNone();
}
PyObject * sndFadeInMusic(PyObject * poSelf, PyObject * poArgs)
PyObject* sndFadeOutMusic(PyObject* poSelf, PyObject* poArgs)
{
char * szFileName;
char* szFileName;
if (!PyTuple_GetString(poArgs, 0, &szFileName))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.FadeInMusic(szFileName);
SoundEngine::Instance().FadeOutMusic(szFileName);
return Py_BuildNone();
}
PyObject * sndFadeOutMusic(PyObject * poSelf, PyObject * poArgs)
PyObject* sndFadeOutAllMusic(PyObject* poSelf, PyObject* poArgs)
{
char * szFileName;
if (!PyTuple_GetString(poArgs, 0, &szFileName))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.FadeOutMusic(szFileName);
SoundEngine::Instance().FadeOutAllMusic();
return Py_BuildNone();
}
PyObject * sndFadeOutAllMusic(PyObject * poSelf, PyObject * poArgs)
PyObject* sndFadeLimitOutMusic(PyObject* poSelf, PyObject* poArgs)
{
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.FadeOutAllMusic();
return Py_BuildNone();
}
PyObject * sndFadeLimitOutMusic(PyObject * poSelf, PyObject * poArgs)
{
char * szFileName;
char* szFileName;
if (!PyTuple_GetString(poArgs, 0, &szFileName))
return Py_BuildException();
@@ -82,95 +66,74 @@ PyObject * sndFadeLimitOutMusic(PyObject * poSelf, PyObject * poArgs)
if (!PyTuple_GetFloat(poArgs, 1, &fLimitVolume))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.FadeLimitOutMusic(szFileName, fLimitVolume);
SoundEngine::Instance().FadeOutMusic(szFileName, fLimitVolume);
return Py_BuildNone();
}
PyObject * sndStopAllSound(PyObject * poSelf, PyObject * poArgs)
PyObject* sndStopAllSound(PyObject* poSelf, PyObject* poArgs)
{
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.StopAllSound3D();
SoundEngine::Instance().StopAllSound3D();
return Py_BuildNone();
}
PyObject * sndSetMusicVolume(PyObject * poSelf, PyObject * poArgs)
PyObject* sndSetMasterVolume(PyObject* poSelf, PyObject* poArgs)
{
float fVolume;
if (!PyTuple_GetFloat(poArgs, 0, &fVolume))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.SetMusicVolume(fVolume);
SoundEngine::Instance().SetMasterVolume(fVolume);
return Py_BuildNone();
}
PyObject * sndSetSoundVolumef(PyObject * poSelf, PyObject * poArgs)
PyObject* sndSetMusicVolume(PyObject* poSelf, PyObject* poArgs)
{
float fVolume;
if (!PyTuple_GetFloat(poArgs, 0, &fVolume))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.SetSoundVolume(fVolume);
SoundEngine::Instance().SetMusicVolume(fVolume);
return Py_BuildNone();
}
PyObject * sndSetSoundVolume(PyObject * poSelf, PyObject * poArgs)
PyObject* sndSetSoundVolumef(PyObject* poSelf, PyObject* poArgs)
{
int iVolume;
if (!PyTuple_GetInteger(poArgs, 0, &iVolume))
float fVolume;
if (!PyTuple_GetFloat(poArgs, 0, &fVolume))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.SetSoundVolume(iVolume);
SoundEngine::Instance().SetSoundVolume(fVolume);
return Py_BuildNone();
}
PyObject * sndSetSoundScale(PyObject * poSelf, PyObject * poArgs)
PyObject* sndSetSoundVolume(PyObject* poSelf, PyObject* poArgs)
{
float fScale;
if (!PyTuple_GetFloat(poArgs, 0, &fScale))
float volume;
if (!PyTuple_GetFloat(poArgs, 0, &volume))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.SetSoundScale(fScale);
return Py_BuildNone();
}
PyObject * sndSetAmbienceSoundScale(PyObject * poSelf, PyObject * poArgs)
{
float fScale;
if (!PyTuple_GetFloat(poArgs, 0, &fScale))
return Py_BuildException();
CSoundManager& rkSndMgr=CSoundManager::Instance();
rkSndMgr.SetAmbienceSoundScale(fScale);
SoundEngine::Instance().SetSoundVolume(volume / 100.0f);
return Py_BuildNone();
}
void initsnd()
{
static PyMethodDef s_methods[] =
static PyMethodDef s_methods[] =
{
{ "PlaySound", sndPlaySound, METH_VARARGS },
{ "PlaySound", sndPlaySound2D, METH_VARARGS },
{ "PlaySound3D", sndPlaySound3D, METH_VARARGS },
{ "PlayMusic", sndPlayMusic, METH_VARARGS },
{ "FadeInMusic", sndFadeInMusic, METH_VARARGS },
{ "FadeOutMusic", sndFadeOutMusic, METH_VARARGS },
{ "FadeOutAllMusic", sndFadeOutAllMusic, METH_VARARGS },
{ "FadeLimitOutMusic", sndFadeLimitOutMusic, METH_VARARGS },
{ "StopAllSound", sndStopAllSound, METH_VARARGS },
{ "SetMusicVolumef", sndSetMusicVolume, METH_VARARGS },
{ "SetMasterVolume", sndSetMasterVolume, METH_VARARGS },
{ "SetMusicVolume", sndSetMusicVolume, METH_VARARGS },
{ "SetSoundVolumef", sndSetSoundVolumef, METH_VARARGS },
{ "SetSoundVolume", sndSetSoundVolume, METH_VARARGS },
{ "SetSoundScale", sndSetSoundScale, METH_VARARGS },
{ "SetAmbienceSoundScale", sndSetAmbienceSoundScale, METH_VARARGS },
{ NULL, NULL, NULL },
};
Py_InitModule("snd", s_methods);
}
}

View File

@@ -632,7 +632,7 @@ void CPythonSystem::ChangeSystem()
else
CScreen::SetShadowFlag(false);
*/
CSoundManager& rkSndMgr = CSoundManager::Instance();
SoundEngine& rkSndMgr = SoundEngine::Instance();
/*
float fMusicVolume;
if (0 == m_Config.music_volume)

View File

@@ -13,7 +13,7 @@
#include "eterPythonLib/StdAfx.h"
#include "gameLib/StdAfx.h"
#include "scriptLib/StdAfx.h"
#include "milesLib/StdAfx.h"
#include "AudioLib/StdAfx.h"
#include "EffectLib/StdAfx.h"
#include "PRTerrainLib/StdAfx.h"
#include "SpeedTreeLib/StdAfx.h"