client almost builds

This commit is contained in:
d1str4ught
2025-08-19 00:20:40 +02:00
parent 4be475f111
commit be56f3f31a
1090 changed files with 126610 additions and 14032 deletions

View File

@@ -2,7 +2,8 @@
add_library(MilesLib STATIC ${FILE_SOURCES})
# target_link_libraries(MilesLib
# )
target_link_libraries(MilesLib
lzo2
)
GroupSourcesByFolder(MilesLib)

135
src/MilesLib/MSSFileAPI.cpp Normal file
View File

@@ -0,0 +1,135 @@
#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

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

View File

@@ -0,0 +1,56 @@
#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

@@ -0,0 +1,30 @@
#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

@@ -0,0 +1,17 @@
#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

@@ -0,0 +1,29 @@
#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

@@ -0,0 +1,31 @@
#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

@@ -0,0 +1,15 @@
#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,70 +0,0 @@
#include "Stdafx.h"
#include "SoundBase.h"
HDIGDRIVER CSoundBase::ms_DIGDriver = NULL;
TSoundDataMap CSoundBase::ms_dataMap;
TProvider * CSoundBase::ms_pProviderDefault = NULL;
std::vector<TProvider> CSoundBase::ms_ProviderVector;
bool CSoundBase::ms_bInitialized = false;
int CSoundBase::ms_iRefCount = 0;
CSoundBase::CSoundBase()
{
}
CSoundBase::~CSoundBase()
{
}
void CSoundBase::Destroy()
{
if (ms_iRefCount > 1)
{
--ms_iRefCount;
return;
}
ms_iRefCount = 0;
if (!ms_dataMap.empty())
{
TSoundDataMap::iterator i;
for (i = ms_dataMap.begin(); i != ms_dataMap.end(); ++i)
{
CSoundData * pSoundData = i->second;
delete pSoundData;
}
ms_dataMap.clear();
}
AIL_shutdown();
}
void CSoundBase::Initialize()
{
++ms_iRefCount;
if (ms_iRefCount > 1)
return;
AIL_set_redist_directory("miles");
AIL_startup();
ms_ProviderVector.clear();
ms_dataMap.clear();
}
DWORD CSoundBase::GetFileCRC(const char * filename)
{
return GetCRC32(filename, strlen(filename));
}
CSoundData * CSoundBase::AddFile(DWORD dwFileCRC, const char* filename)
{
CSoundData * pSoundData = new CSoundData;
pSoundData->Assign(filename);
ms_dataMap.insert(TSoundDataMap::value_type(dwFileCRC, pSoundData));
return pSoundData;
}

View File

@@ -1,37 +0,0 @@
#ifndef __MILESLIB_CSOUNDBASE_H__
#define __MILESLIB_CSOUNDBASE_H__
#include <map>
#include <vector>
#include "SoundData.h"
typedef struct SProvider
{
char* name;
HPROVIDER hProvider;
} TProvider;
typedef std::map<DWORD, CSoundData*> TSoundDataMap;
class CSoundBase
{
public:
CSoundBase();
virtual ~CSoundBase();
void Initialize();
void Destroy();
CSoundData * AddFile(DWORD dwFileCRC, const char* filename);
DWORD GetFileCRC(const char* filename);
protected:
static int ms_iRefCount;
static HDIGDRIVER ms_DIGDriver;
static TProvider * ms_pProviderDefault;
static std::vector<TProvider> ms_ProviderVector;
static TSoundDataMap ms_dataMap;
static bool ms_bInitialized;
};
#endif

View File

@@ -1,212 +0,0 @@
#include "StdAfx.h"
#include "SoundData.h"
#include "../EterPack/EterPackManager.h"
#include "../eterBase/Timer.h"
bool CSoundData::ms_isSoundFile[SOUND_FILE_MAX_NUM];
CMappedFile CSoundData::ms_SoundFile[SOUND_FILE_MAX_NUM];
const char * CSoundData::GetFileName()
{
return m_filename;
}
void CSoundData::Assign(const char* filename)
{
assert(m_assigned == false);
strncpy(m_filename, filename, sizeof(m_filename)-1);
m_assigned = true;
}
LPVOID CSoundData::Get()
{
++m_iRefCount;
m_dwAccessTime = ELTimer_GetMSec();
if (!m_data)
ReadFromDisk();
if (m_flag & FLAG_DATA_SIZE)
return ((S32 *) m_data + 1);
else
return (m_data);
}
ULONG CSoundData::GetSize()
{
return m_size;
}
void CSoundData::Release()
{
assert(m_iRefCount != 0);
--m_iRefCount;
m_dwAccessTime = ELTimer_GetMSec();
}
DWORD CSoundData::GetPlayTime()
{
return m_dwPlayTime;
}
void CSoundData::SetPlayTime(DWORD dwPlayTime)
{
m_dwPlayTime = dwPlayTime;
}
DWORD CSoundData::GetAccessTime()
{
return m_dwAccessTime;
}
bool CSoundData::ReadFromDisk()
{
assert(m_assigned == true);
LARGE_INTEGER start;
QueryPerformanceCounter(&start);
U32* s = (U32 *) AIL_file_read(m_filename, FILE_READ_WITH_SIZE);
if (s == NULL)
return false;
S32 type = AIL_file_type(s + 1, s[0]);
AILSOUNDINFO info;
switch (type)
{
case AILFILETYPE_PCM_WAV:
{
m_data = s;
m_size = *((S32 *) s);
m_flag |= FLAG_DATA_SIZE;
}
break;
case AILFILETYPE_ADPCM_WAV: // 3D »ç¿îµå´Â decompress ÇØ¾ß ÇÔ.
{
AIL_WAV_info(s + 1, &info);
AIL_decompress_ADPCM(&info, &m_data, &m_size);
AIL_mem_free_lock(s);
}
break;
case AILFILETYPE_MPEG_L3_AUDIO:
{
AIL_decompress_ASI(s + 1, *((S32 *) s), m_filename, &m_data, &m_size, 0);
AIL_mem_free_lock(s);
}
break;
default:
assert(!"Unknown File Type");
AIL_mem_free_lock(s);
return false;
}
return true;
}
bool CSoundData::isSlotIndex(DWORD dwIndex)
{
if (dwIndex >= SOUND_FILE_MAX_NUM)
return false;
if (!ms_isSoundFile[dwIndex])
return false;
return true;
}
int CSoundData::GetEmptySlotIndex()
{
for (int i = 0; i < SOUND_FILE_MAX_NUM; ++i)
{
if (!ms_isSoundFile[i])
return i;
}
return -1;
}
U32 AILCALLBACK CSoundData::open_callback(char const * filename, U32 *file_handle)
{
int iIndex = GetEmptySlotIndex();
if (-1 == iIndex)
return 0;
LPCVOID pMap;
if (!CEterPackManager::Instance().Get(ms_SoundFile[iIndex], filename, &pMap))
return 0;
ms_isSoundFile[iIndex] = true;
*file_handle = iIndex;
return 1;
}
void AILCALLBACK CSoundData::close_callback(U32 file_handle)
{
if (!isSlotIndex(file_handle))
return;
ms_SoundFile[file_handle].Destroy();
ms_isSoundFile[file_handle] = false;
}
S32 AILCALLBACK CSoundData::seek_callback(U32 file_handle, S32 offset, U32 type)
{
if (!isSlotIndex(file_handle))
return 0;
return ms_SoundFile[file_handle].Seek(offset, type);
}
U32 AILCALLBACK CSoundData::read_callback(U32 file_handle, void * buffer, U32 bytes)
{
if (!isSlotIndex(file_handle))
return 0;
DWORD dwRealSize = min(ms_SoundFile[file_handle].Size(), bytes);
ms_SoundFile[file_handle].Read(buffer, dwRealSize);
return dwRealSize;
}
void CSoundData::SetPackMode()
{
// if sound data reads from pack file, the callbacks of the MSS should be changed.
AIL_set_file_callbacks(open_callback, close_callback, seek_callback, read_callback);
for (int i = 0; i < SOUND_FILE_MAX_NUM; ++i)
ms_isSoundFile[i] = false;
}
void CSoundData::Destroy()
{
if (m_data)
{
AIL_mem_free_lock(m_data);
m_data = NULL;
}
}
CSoundData::CSoundData() :
m_assigned(false),
m_iRefCount(0),
m_dwPlayTime(0),
m_dwAccessTime(ELTimer_GetMSec()),
m_size(0),
m_data(NULL),
m_flag(0)
{
}
CSoundData::~CSoundData()
{
Destroy();
}

View File

@@ -1,59 +0,0 @@
#ifndef __MILESLIB_CSOUNDDATA_H__
#define __MILESLIB_CSOUNDDATA_H__
#include <mss.h>
#include "../eterBase/MappedFile.h"
class CSoundData
{
public:
enum
{
FLAG_DATA_SIZE = 1,
SOUND_FILE_MAX_NUM = 5,
};
public:
static void SetPackMode();
CSoundData();
virtual ~CSoundData();
void Assign(const char* filename);
LPVOID Get();
ULONG GetSize();
void Release();
DWORD GetAccessTime();
const char * GetFileName();
void SetPlayTime(DWORD dwPlayTime);
DWORD GetPlayTime();
protected:
bool ReadFromDisk();
void Destroy();
protected:
char m_filename[128];
int m_iRefCount;
DWORD m_dwAccessTime;
DWORD m_dwPlayTime;
ULONG m_size;
LPVOID m_data;
long m_flag;
bool m_assigned;
private:
static U32 AILCALLBACK open_callback(char const * filename, U32 *file_handle);
static void AILCALLBACK close_callback(U32 file_handle);
static S32 AILCALLBACK seek_callback(U32 file_handle, S32 offset, U32 type);
static U32 AILCALLBACK read_callback(U32 file_handle, void *buffer, U32 bytes);
static bool isSlotIndex(DWORD dwIndex);
static int GetEmptySlotIndex();
static bool ms_isSoundFile[SOUND_FILE_MAX_NUM];
static CMappedFile ms_SoundFile[SOUND_FILE_MAX_NUM];
};
#endif

View File

@@ -1,118 +0,0 @@
#ifndef __MILESLIB_CSOUNDINSTANCE_H__
#define __MILESLIB_CSOUNDINSTANCE_H__
#include "SoundBase.h"
class ISoundInstance : public CSoundBase
{
public:
ISoundInstance() {}
virtual ~ISoundInstance() {}
virtual bool Initialize() = 0;
virtual void Destroy() = 0;
virtual bool SetSound(CSoundData* pSound) = 0;
virtual void Play(int iLoopCount = 1, DWORD dwPlayCycleTimeLimit = 0) const = 0;
virtual void Pause() const = 0;
virtual void Resume() const = 0;
virtual void Stop() = 0;
virtual void GetVolume(float& rfVolume) const = 0;
virtual void SetVolume(float volume) const = 0;
virtual bool IsDone() const = 0;
virtual void SetPosition(float x, float y, float z) const = 0;
virtual void SetOrientation(float x_face, float y_face, float z_face,
float x_normal, float y_normal, float z_normal) const = 0;
virtual void SetVelocity(float x, float y, float z, float fMagnitude) const = 0;
};
class CSoundInstance2D : public ISoundInstance
{
public:
CSoundInstance2D();
virtual ~CSoundInstance2D();
public: // from interface
bool Initialize();
void Destroy();
bool SetSound(CSoundData* pSound);
void Play(int iLoopCount = 1, DWORD dwPlayCycleTimeLimit = 0) const;
void Pause() const;
void Resume() const;
void Stop();
void GetVolume(float& rfVolume) const;
void SetVolume(float volume) const;
bool IsDone() const;
void SetPosition(float x, float y, float z) const;
void SetOrientation(float x_face, float y_face, float z_face,
float x_normal, float y_normal, float z_normal) const;
void SetVelocity(float fx, float fy, float fz, float fMagnitude) const;
private:
HSAMPLE m_sample;
CSoundData* m_pSoundData;
};
class CSoundInstance3D : public ISoundInstance
{
public:
CSoundInstance3D();
virtual ~CSoundInstance3D();
public: // from interface
bool Initialize();
void Destroy();
bool SetSound(CSoundData * pSound);
void Play(int iLoopCount = 1, DWORD dwPlayCycleTimeLimit = 0) const;
void Pause() const;
void Resume() const;
void Stop();
void GetVolume(float& rfVolume) const;
void SetVolume(float volume) const;
bool IsDone() const;
void SetPosition(float x, float y, float z) const;
void SetOrientation(float x_face, float y_face, float z_face,
float x_normal, float y_normal, float z_normal) const;
void SetVelocity(float fx, float fy, float fz, float fMagnitude) const;
void UpdatePosition(float fElapsedTime);
private:
H3DSAMPLE m_sample;
CSoundData * m_pSoundData;
};
class CSoundInstanceStream : public ISoundInstance
{
public:
CSoundInstanceStream();
virtual ~CSoundInstanceStream();
public: // from interface
bool Initialize();
void Destroy();
void SetStream(HSTREAM stream);
bool SetSound(CSoundData* pSound);
void Play(int iLoopCount = 1, DWORD dwPlayCycleTimeLimit = 0) const;
void Pause() const;
void Resume() const;
void Stop();
void GetVolume(float& rfVolume) const;
void SetVolume(float volume) const;
bool IsDone() const;
bool IsData() const;
void SetPosition(float x, float y, float z) const;
void SetOrientation(float x_face, float y_face, float z_face,
float x_normal, float y_normal, float z_normal) const;
void SetVelocity(float fx, float fy, float fz, float fMagnitude) const;
private:
HSTREAM m_stream;
};
#endif

View File

@@ -1,121 +0,0 @@
#include "stdafx.h"
#include "SoundManager2D.h"
CSoundInstance2D::CSoundInstance2D() : m_sample(NULL), m_pSoundData(NULL)
{
}
CSoundInstance2D::~CSoundInstance2D()
{
Destroy();
}
void CSoundInstance2D::Destroy()
{
SAFE_RELEASE(m_pSoundData);
if (m_sample)
{
AIL_release_sample_handle(m_sample);
m_sample = NULL;
}
}
bool CSoundInstance2D::Initialize()
{
if (m_sample)
return true;
m_sample = AIL_allocate_sample_handle(ms_DIGDriver);
return m_sample ? true : false;
}
bool CSoundInstance2D::SetSound(CSoundData * pSoundData)
{
assert(m_sample != NULL && pSoundData != NULL);
// 레퍼런스 카운트가 1이 될 때 로드를 해야 제대로 사이즈가 리턴
// 되므로 반드시 Get을 호출 하고 진행해야 한다.
// 또, m_pSoundData가 pSoundData와 같고 m_pSoundData의 레퍼런스
// 카운터가 1일 경우, 불필요하게 로드가 일어나므로 미리 레퍼런스
// 카운터를 올려놔야 한다.
LPVOID lpData = pSoundData->Get();
AIL_init_sample(m_sample);
if (AIL_set_sample_file(m_sample, lpData, pSoundData->GetSize()) == NULL)
{
if (m_pSoundData != NULL)
{
m_pSoundData->Release();
m_pSoundData = NULL;
}
pSoundData->Release();
TraceError("%s: %s", AIL_last_error(), pSoundData->GetFileName());
return false;
}
if (m_pSoundData != NULL)
{
m_pSoundData->Release();
m_pSoundData = NULL;
}
m_pSoundData = pSoundData;
return true;
}
bool CSoundInstance2D::IsDone() const
{
return AIL_sample_status(m_sample) == SMP_DONE;
}
void CSoundInstance2D::Play(int iLoopCount, DWORD dwPlayCycleTimeLimit) const
{
AIL_set_sample_loop_count(m_sample, iLoopCount);
AIL_start_sample(m_sample);
}
void CSoundInstance2D::Pause() const
{
AIL_stop_sample(m_sample);
}
void CSoundInstance2D::Resume() const
{
AIL_resume_sample(m_sample);
}
void CSoundInstance2D::Stop()
{
AIL_end_sample(m_sample);
m_sample = NULL;
}
void CSoundInstance2D::GetVolume(float& rfVolume) const
{
AIL_sample_volume_pan(m_sample, &rfVolume, NULL);
}
void CSoundInstance2D::SetVolume(float volume) const
{
volume = max(0.0f, min(1.0f, volume));
AIL_set_sample_volume_pan(m_sample, volume, 0.5f);
}
void CSoundInstance2D::SetPosition(float x, float y, float z) const
{
assert(!"must not call this method");
}
void CSoundInstance2D::SetOrientation(float x_face, float y_face, float z_face,
float x_normal, float y_normal, float z_normal) const
{
assert(!"must not call this method");
}
void CSoundInstance2D::SetVelocity(float fx, float fy, float fz, float fMagnitude) const
{
assert(!"must not call this method");
}

View File

@@ -1,137 +0,0 @@
#include "stdafx.h"
#include "SoundManager3D.h"
#include "../eterBase/Timer.h"
CSoundInstance3D::CSoundInstance3D() : m_sample(NULL), m_pSoundData(NULL)
{
}
CSoundInstance3D::~CSoundInstance3D()
{
Destroy();
}
void CSoundInstance3D::Destroy()
{
SAFE_RELEASE(m_pSoundData);
if (m_sample)
{
AIL_release_3D_sample_handle(m_sample);
m_sample = NULL;
}
}
bool CSoundInstance3D::Initialize()
{
if (m_sample)
return true;
m_sample = AIL_allocate_3D_sample_handle(ms_pProviderDefault->hProvider);
return m_sample ? true : false;
}
bool CSoundInstance3D::SetSound(CSoundData* pSoundData)
{
assert(m_sample != NULL && pSoundData != NULL);
// 레퍼런스 카운트가 1이 될 때 로드를 해야 제대로 사이즈가 리턴
// 되므로 반드시 Get을 호출 하고 진행해야 한다.
// 또, m_pSoundData가 pSoundData와 같고 m_pSoundData의 레퍼런스
// 카운터가 1일 경우, 불필요하게 로드가 일어나므로 미리 레퍼런스
// 카운터를 올려놔야 한다.
LPVOID lpData = pSoundData->Get();
if (m_pSoundData != NULL)
{
m_pSoundData->Release();
m_pSoundData = NULL;
}
if (AIL_set_3D_sample_file(m_sample, lpData) == NULL)
{
TraceError("%s: %s", AIL_last_error(), pSoundData->GetFileName());
pSoundData->Release();
return false;
}
m_pSoundData = pSoundData;
AIL_set_3D_position(m_sample, 0.0F, 0.0F, 0.0F);
AIL_auto_update_3D_position(m_sample, 0);
return true;
}
bool CSoundInstance3D::IsDone() const
{
return AIL_3D_sample_status(m_sample) == SMP_DONE;
}
void CSoundInstance3D::Play(int iLoopCount, DWORD dwPlayCycleTimeLimit) const
{
if (!m_pSoundData)
return;
DWORD dwCurTime = ELTimer_GetMSec();
if (dwCurTime - m_pSoundData->GetPlayTime() < dwPlayCycleTimeLimit)
return;
m_pSoundData->SetPlayTime(dwCurTime);
AIL_set_3D_sample_loop_count(m_sample, iLoopCount);
AIL_start_3D_sample(m_sample);
}
void CSoundInstance3D::Pause() const
{
AIL_stop_3D_sample(m_sample);
}
void CSoundInstance3D::Resume() const
{
AIL_resume_3D_sample(m_sample);
}
void CSoundInstance3D::Stop()
{
AIL_end_3D_sample(m_sample);
// m_sample = NULL;
// NOTE : IsDone을 체크하려면 m_sample이 살아있어야 합니다 - [levites]
}
void CSoundInstance3D::GetVolume(float& rfVolume) const
{
rfVolume = AIL_3D_sample_volume(m_sample);
}
void CSoundInstance3D::SetVolume(float volume) const
{
volume = max(0.0f, min(1.0f, volume));
AIL_set_3D_sample_volume(m_sample, volume);
}
void CSoundInstance3D::SetPosition(float x, float y, float z) const
{
AIL_set_3D_position(m_sample, x, y, -z);
}
void CSoundInstance3D::SetOrientation(float x_face, float y_face, float z_face,
float x_normal, float y_normal, float z_normal) const
{
assert(!" CSoundInstance3D::SetOrientation - 사용 하지 않는 함수");
// AIL_set_3D_orientation(m_sample,
// x_face, y_face, z_face,
// x_normal, y_normal, z_normal);
}
void CSoundInstance3D::SetVelocity(float fDistanceX, float fDistanceY, float fDistanceZ, float fNagnitude) const
{
AIL_set_3D_velocity(m_sample, fDistanceX, fDistanceY, fDistanceZ, fNagnitude);
AIL_auto_update_3D_position(m_sample, 1);
}
void CSoundInstance3D::UpdatePosition(float fElapsedTime)
{
AIL_update_3D_position(m_sample, fElapsedTime);
}

View File

@@ -1,114 +0,0 @@
#include "stdafx.h"
#include "SoundInstance.h"
CSoundInstanceStream::CSoundInstanceStream() : m_stream(NULL)
{
}
CSoundInstanceStream::~CSoundInstanceStream()
{
Destroy();
}
void CSoundInstanceStream::Destroy()
{
if (m_stream != NULL)
{
AIL_close_stream(m_stream);
m_stream = NULL;
}
}
bool CSoundInstanceStream::Initialize()
{
return true;
}
void CSoundInstanceStream::SetStream(HSTREAM stream)
{
m_stream = stream;
}
bool CSoundInstanceStream::IsDone() const
{
return AIL_stream_status(m_stream) == -1;
}
bool CSoundInstanceStream::IsData() const
{
if (m_stream)
return true;
return false;
}
void CSoundInstanceStream::Play(int count, DWORD dwPlayCycleTimeLimit) const
{
if (!IsData())
return;
AIL_set_stream_loop_count(m_stream, count);
AIL_start_stream(m_stream);
}
void CSoundInstanceStream::Pause() const
{
if (!IsData())
return;
AIL_pause_stream(m_stream, 1);
}
void CSoundInstanceStream::Resume() const
{
if (!IsData())
return;
AIL_pause_stream(m_stream, 0);
}
void CSoundInstanceStream::Stop()
{
if (!IsData())
return;
AIL_close_stream(m_stream);
m_stream = NULL;
}
void CSoundInstanceStream::GetVolume(float& rfVolume) const
{
float tmp;
if (!IsData())
return;
AIL_stream_volume_levels(m_stream, &rfVolume, &tmp);
}
void CSoundInstanceStream::SetVolume(float volume) const
{
if (!IsData())
return;
volume = max(0.0f, min(1.0f, volume));
AIL_set_stream_volume_levels(m_stream, volume, volume);
}
bool CSoundInstanceStream::SetSound(CSoundData* pSound)
{
return true;
}
void CSoundInstanceStream::SetPosition(float x, float y, float z) const
{
}
void CSoundInstanceStream::SetOrientation(float x_face, float y_face, float z_face,
float x_normal, float y_normal, float z_normal) const
{
}
void CSoundInstanceStream::SetVelocity(float fx, float fy, float fz, float fMagnitude) const
{
}

View File

@@ -1,646 +1,393 @@
#include "StdAfx.h"
#include <math.h>
#include "SoundManager.h"
#include "../EterBase/Timer.h"
CSoundManager2D CSoundManager::ms_SoundManager2D;
CSoundManager3D CSoundManager::ms_SoundManager3D;
CSoundManagerStream CSoundManager::ms_SoundManagerStream;
#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)
{
m_bInitialized = FALSE;
m_isSoundDisable = FALSE;
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;
for (int i = 0; i < CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM; ++i)
{
TMusicInstance & rInstance = m_MusicInstances[i];
rInstance.dwMusicFileNameCRC = 0;
rInstance.MusicState = MUSIC_STATE_OFF;
rInstance.fVolume = 0.0f;
rInstance.fVolumeSpeed = 0.0f;
}
// ctor
}
CSoundManager::~CSoundManager()
bool CSoundManager::Create()
{
}
BOOL CSoundManager::Create()
{
if (!ms_SoundManager2D.Initialize()) {
Tracen("CSoundManager::Create - Sound2D::Initialize - FAILURE");
return FALSE;
}
if (!ms_SoundManagerStream.Initialize())
{
Tracen("CSoundManager::Create - SoundStream::Initialize - FAILURE");
return FALSE;
}
if (!ms_SoundManager3D.Initialize())
{
Tracen("CSoundManager::Create - Sound3D::Initialize - FAILURE");
return FALSE;
}
return TRUE;
}
void CSoundManager::Destroy()
{
ms_SoundManagerStream.Destroy();
ms_SoundManager3D.Destroy();
ms_SoundManager2D.Destroy();
m_PlaySoundHistoryMap.clear(); // Fix
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;
m_fxPosition = fx;
m_fyPosition = fy;
m_fzPosition = fz;
}
void CSoundManager::SetDirection(float fxDir, float fyDir, float fzDir, float fxUp, float fyUp, float fzUp)
{
ms_SoundManager3D.SetListenerDirection(fxDir, fyDir, fzDir, fxUp, fyUp, fzUp);
if (!m_driver)
return;
AIL_set_listener_3D_orientation(m_driver, fxDir, fyDir, -fzDir, fxUp, fyUp, -fzUp);
}
void CSoundManager::Update()
{
// Update Information about 3D Sound
ms_SoundManager3D.SetListenerPosition(0.0f, 0.0f, 0.0f);
for (auto it = m_sounds2d.begin(); it != m_sounds2d.end();)
{
if (it->IsDone())
it = m_sounds2d.erase(it);
else
++it;
}
for (int i = 0; i < CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM; ++i)
{
TMusicInstance & rMusicInstance = m_MusicInstances[i];
if (MUSIC_STATE_OFF == rMusicInstance.MusicState)
continue;
for (auto it = m_sounds3d.begin(); it != m_sounds3d.end();)
{
if (it->IsDone())
it = m_sounds3d.erase(it);
else
++it;
}
switch (rMusicInstance.MusicState)
{
case MUSIC_STATE_FADE_IN:
rMusicInstance.fVolume += rMusicInstance.fVolumeSpeed;
if (rMusicInstance.fVolume >= GetMusicVolume())
{
rMusicInstance.fVolume = GetMusicVolume();
rMusicInstance.fVolumeSpeed = 0.0f;
rMusicInstance.MusicState = MUSIC_STATE_PLAY;
}
{
CSoundInstanceStream * pInstance = ms_SoundManagerStream.GetInstance(i);
if (pInstance)
pInstance->SetVolume(rMusicInstance.fVolume);
}
break;
case MUSIC_STATE_FADE_LIMIT_OUT:
rMusicInstance.fVolume -= rMusicInstance.fVolumeSpeed;
if (rMusicInstance.fVolume <= rMusicInstance.fLimitVolume)
{
rMusicInstance.fVolume = rMusicInstance.fLimitVolume;
rMusicInstance.fVolumeSpeed = 0.0f;
rMusicInstance.MusicState = MUSIC_STATE_PLAY;
}
{
CSoundInstanceStream * pInstance = ms_SoundManagerStream.GetInstance(i);
if (pInstance)
pInstance->SetVolume(rMusicInstance.fVolume);
}
break;
case MUSIC_STATE_FADE_OUT:
rMusicInstance.fVolume -= rMusicInstance.fVolumeSpeed;
if (rMusicInstance.fVolume <= 0.0f)
{
rMusicInstance.fVolume = 0.0f;
rMusicInstance.fVolumeSpeed = 0.0f;
rMusicInstance.MusicState = MUSIC_STATE_OFF;
StopMusic(i);
}
{
CSoundInstanceStream * pInstance = ms_SoundManagerStream.GetInstance(i);
if (pInstance)
pInstance->SetVolume(rMusicInstance.fVolume);
}
break;
}
}
}
void CSoundManager::UpdateSoundData(DWORD dwcurTime, const NSound::TSoundDataVector * c_pSoundDataVector)
{
assert(!"CSoundManager::UpdateSoundData");
}
void CSoundManager::UpdateSoundData(float fx, float fy, float fz, DWORD dwcurTime, const NSound::TSoundDataVector * c_pSoundDataVector)
{
assert(!"CSoundManager::UpdateSoundData");
}
void CSoundManager::UpdateSoundInstance(float fx, float fy, float fz, DWORD dwcurFrame, const NSound::TSoundInstanceVector * c_pSoundInstanceVector, BOOL bCheckFrequency)
{
for (DWORD i = 0; i < c_pSoundInstanceVector->size(); ++i)
{
const NSound::TSoundInstance & c_rSoundInstance = c_pSoundInstanceVector->at(i);
if (c_rSoundInstance.dwFrame == dwcurFrame)
{
//Tracenf("PLAY SOUND %s", c_rSoundInstance.strSoundFileName.c_str());
PlayCharacterSound3D(fx, fy, fz, c_rSoundInstance.strSoundFileName.c_str(), bCheckFrequency);
}
}
}
void CSoundManager::UpdateSoundInstance(DWORD dwcurFrame, const NSound::TSoundInstanceVector * c_pSoundInstanceVector)
{
for (DWORD i = 0; i < c_pSoundInstanceVector->size(); ++i)
{
const NSound::TSoundInstance & c_rSoundInstance = c_pSoundInstanceVector->at(i);
if (c_rSoundInstance.dwFrame == dwcurFrame)
{
PlaySound2D(c_rSoundInstance.strSoundFileName.c_str());
}
}
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;
return m_fSoundScale;
}
void CSoundManager::SetSoundScale(float fScale)
{
m_fSoundScale = fScale;
m_fSoundScale = fScale;
}
void CSoundManager::SetAmbienceSoundScale(float fScale)
{
m_fAmbienceSoundScale = fScale;
m_fAmbienceSoundScale = fScale;
}
void CSoundManager::SetSoundVolume(float fVolume)
{
if (m_isSoundDisable)
{
m_fBackupSoundVolume = fVolume;
return;
}
if (m_isSoundDisable)
{
m_fBackupSoundVolume = fVolume;
return;
}
fVolume = fMAX(fVolume, 0.0f);
fVolume = fMIN(fVolume, 1.0f);
m_fSoundVolume = fVolume;
if (!m_isSoundDisable)
{
m_fBackupSoundVolume = fVolume;
}
}
void CSoundManager::__SetMusicVolume(float fVolume)
{
if (m_isSoundDisable)
{
m_fBackupMusicVolume = fVolume;
return;
}
fVolume = fMAX(fVolume, 0.0f);
fVolume = fMIN(fVolume, 1.0f);
m_fMusicVolume = fVolume;
if (!m_isSoundDisable)
{
m_fBackupMusicVolume = fVolume;
}
for (int i = 0; i < CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM; ++i)
{
TMusicInstance & rMusicInstance = m_MusicInstances[i];
if (MUSIC_STATE_OFF == rMusicInstance.MusicState)
continue;
if (MUSIC_STATE_FADE_OUT == rMusicInstance.MusicState)
continue;
rMusicInstance.fVolume = fVolume;
CSoundInstanceStream * pInstance = ms_SoundManagerStream.GetInstance(i);
if (pInstance)
pInstance->SetVolume(fVolume);
}
}
float CSoundManager::__ConvertRatioVolumeToApplyVolume(float fRatioVolume)
{
if (0.1f>fRatioVolume)
return fRatioVolume;
return (float)pow(10.0f, (-1.0f + fRatioVolume));
}
float CSoundManager::__ConvertGradeVolumeToApplyVolume(int nGradeVolume)
{
return __ConvertRatioVolumeToApplyVolume(nGradeVolume/5.0f);
}
void CSoundManager::SetSoundVolumeGrade(int iGrade)
{
float fVolume=__ConvertGradeVolumeToApplyVolume(iGrade);
SetSoundVolume(fVolume);
}
//void CSoundManager::SetMusicVolumeGrade(int iGrade)
//{
// float fVolume=__ConvertGradeVolumeToApplyVolume(iGrade);
// __SetMusicVolume(fVolume);
//}
void CSoundManager::SetSoundVolumeRatio(float fRatio)
{
float fVolume = __ConvertRatioVolumeToApplyVolume(fRatio);
SetSoundVolume(fVolume);
fVolume = std::max(std::min(fVolume, 1.0f), 0.0f);
m_fSoundVolume = fVolume;
m_fBackupSoundVolume = fVolume;
}
void CSoundManager::SetMusicVolume(float fVolume)
{
//float fVolume = __ConvertRatioVolumeToApplyVolume(fRatio);
__SetMusicVolume(fVolume);
}
float CSoundManager::GetSoundVolume()
{
return m_fSoundVolume;
}
if (m_isSoundDisable)
{
m_fBackupMusicVolume = fVolume;
return;
}
float CSoundManager::GetMusicVolume()
{
return m_fMusicVolume;
}
fVolume = std::max(std::min(fVolume, 1.0f), 0.0f);
m_fMusicVolume = fVolume;
m_fBackupMusicVolume = fVolume;
BOOL CSoundManager::GetSoundInstance2D(const char * c_szSoundFileName, ISoundInstance ** ppInstance)
{
*ppInstance = ms_SoundManager2D.GetInstance(c_szSoundFileName);
for (auto &p : m_music)
{
if (MUSIC_STATE_OFF == p.second.MusicState)
continue;
if (MUSIC_STATE_FADE_OUT == p.second.MusicState)
continue;
if (!*ppInstance)
return FALSE;
return TRUE;
}
BOOL CSoundManager::GetSoundInstance3D(const char * c_szFileName, ISoundInstance ** ppInstance)
{
int iIndex = ms_SoundManager3D.SetInstance(c_szFileName);
if (-1 == iIndex)
return FALSE;
*ppInstance = ms_SoundManager3D.GetInstance(iIndex);
if (!*ppInstance)
return FALSE;
return TRUE;
}
void CSoundManager::PlaySound2D(const char * c_szFileName)
{
if (0.0f == GetSoundVolume())
return;
ISoundInstance * pInstance;
if (!GetSoundInstance2D(c_szFileName, &pInstance))
return;
pInstance->SetVolume(GetSoundVolume());
pInstance->Play(1);
}
void CSoundManager::PlaySound3D(float fx, float fy, float fz, const char * c_szFileName, int iPlayCount)
{
if (0.0f == GetSoundVolume())
return;
int iIndex = ms_SoundManager3D.SetInstance(c_szFileName);
if (-1 == iIndex)
return;
ISoundInstance * pInstance = ms_SoundManager3D.GetInstance(iIndex);
if (!pInstance)
return;
pInstance->SetPosition((fx - m_fxPosition) / m_fSoundScale,
(fy - m_fyPosition) / m_fSoundScale,
(fz - m_fzPosition) / m_fSoundScale);
pInstance->SetVolume(GetSoundVolume());
pInstance->Play(iPlayCount);
}
int CSoundManager::PlayAmbienceSound3D(float fx, float fy, float fz, const char * c_szFileName, int iPlayCount)
{
if (0.0f == GetSoundVolume())
return -1;
int iIndex = ms_SoundManager3D.SetInstance(c_szFileName);
if (-1 == iIndex)
return -1;
ISoundInstance * pInstance = ms_SoundManager3D.GetInstance(iIndex);
if (!pInstance)
return -1;
pInstance->SetPosition((fx - m_fxPosition) / m_fAmbienceSoundScale,
(fy - m_fyPosition) / m_fAmbienceSoundScale,
(fz - m_fzPosition) / m_fAmbienceSoundScale);
pInstance->SetVolume(GetSoundVolume());
pInstance->Play(iPlayCount);
return iIndex;
}
void CSoundManager::PlayCharacterSound3D(float fx, float fy, float fz, const char * c_szFileName, 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;
std::map<std::string, float>::iterator itor = m_PlaySoundHistoryMap.find(c_szFileName);
if (m_PlaySoundHistoryMap.end() != itor)
{
float fTime = itor->second;
if (CTimer::Instance().GetCurrentSecond() - fTime < 0.3f)
{
//Tracef("똑같은 소리가 0.3초 내에 다시 플레이 %s\n", c_szFileName);
return;
}
}
m_PlaySoundHistoryMap.erase(c_szFileName);
m_PlaySoundHistoryMap.insert(std::map<std::string, float>::value_type(c_szFileName, CTimer::Instance().GetCurrentSecond()));
}
ISoundInstance * pInstance;
if (!GetSoundInstance3D(c_szFileName, &pInstance))
return;
pInstance->SetPosition((fx - m_fxPosition) / m_fSoundScale,
(fy - m_fyPosition) / m_fSoundScale,
(fz - m_fzPosition) / m_fSoundScale);
pInstance->SetVolume(GetSoundVolume());
pInstance->Play(1);
}
void CSoundManager::StopSound3D(int iIndex)
{
ISoundInstance * pInstance = ms_SoundManager3D.GetInstance(iIndex);
if (!pInstance)
return;
pInstance->Stop();
//bool bisDone = pInstance->IsDone();
}
void CSoundManager::SetSoundVolume3D(int iIndex, float fVolume)
{
ISoundInstance * pInstance = ms_SoundManager3D.GetInstance(iIndex);
if (!pInstance)
return;
pInstance->SetVolume(fVolume);
}
void CSoundManager::StopAllSound3D()
{
for (int i = 0; i < CSoundManager3D::INSTANCE_MAX_COUNT; ++i)
{
StopSound3D(i);
}
m_PlaySoundHistoryMap.clear(); // Fix
}
void CSoundManager::PlayMusic(const char * c_szFileName)
{
PlayMusic(0, c_szFileName, GetMusicVolume(), 0.0f);
}
void CSoundManager::FadeInMusic(const char * c_szFileName, float fVolumeSpeed)
{
DWORD dwIndex;
if (GetMusicIndex(c_szFileName, &dwIndex))
{
m_MusicInstances[dwIndex].MusicState = MUSIC_STATE_FADE_IN;
m_MusicInstances[dwIndex].fVolumeSpeed = fVolumeSpeed;
return;
}
FadeOutAllMusic();
//Tracenf("FadeInMusic: %s", c_szFileName);
for (int i = 0; i < CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM; ++i)
{
TMusicInstance & rMusicInstance = m_MusicInstances[i];
if (MUSIC_STATE_OFF != rMusicInstance.MusicState)
continue;
PlayMusic(i, c_szFileName, 0.0f, fVolumeSpeed);
return;
}
return;
// If there is no empty music slot, then play music on slot 0.
/*
StopMusic(0);
PlayMusic(0, c_szFileName, 0.0f, fVolumeSpeed);
*/
}
void CSoundManager::FadeLimitOutMusic(const char * c_szFileName, float fLimitVolume, float fVolumeSpeed)
{
//Tracenf("FadeLimitOutMusic: %s", c_szFileName);
DWORD dwIndex;
if (!GetMusicIndex(c_szFileName, &dwIndex))
{
Tracenf("FadeOutMusic: %s - ERROR NOT EXIST", c_szFileName);
return;
}
if (dwIndex >= CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM)
{
Tracenf("FadeOutMusic: %s - ERROR OUT OF RANGE", c_szFileName);
return;
}
SMusicInstance& rkMusicInst=m_MusicInstances[dwIndex];
rkMusicInst.MusicState = MUSIC_STATE_FADE_LIMIT_OUT;
rkMusicInst.fVolumeSpeed = fVolumeSpeed;
rkMusicInst.fLimitVolume = __ConvertRatioVolumeToApplyVolume(fLimitVolume);
//Tracenf("LimitVolume %f(%f)", fLimitVolume, rkMusicInst.fLimitVolume);
}
void CSoundManager::FadeOutMusic(const char * c_szFileName, float fVolumeSpeed)
{
//Tracenf("FadeOutMusic: %s", c_szFileName);
DWORD dwIndex;
if (!GetMusicIndex(c_szFileName, &dwIndex))
{
Tracenf("FadeOutMusic: %s - ERROR NOT EXIST", c_szFileName);
return;
}
if (dwIndex >= CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM)
{
Tracenf("FadeOutMusic: %s - ERROR OUT OF RANGE", c_szFileName);
return;
}
m_MusicInstances[dwIndex].MusicState = MUSIC_STATE_FADE_OUT;
m_MusicInstances[dwIndex].fVolumeSpeed = fVolumeSpeed;
}
void CSoundManager::FadeOutAllMusic()
{
//Tracenf("FadeOutAllMusic");
for (int i = 0; i < CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM; ++i)
{
if (MUSIC_STATE_OFF == m_MusicInstances[i].MusicState)
continue;
m_MusicInstances[i].MusicState = MUSIC_STATE_FADE_OUT;
m_MusicInstances[i].fVolumeSpeed = 0.01f;
}
p.second.fVolume = fVolume;
p.second.stream.SetVolume(fVolume);
}
}
void CSoundManager::SaveVolume()
{
// NOTE : 두번 이상 Save를 시도할때는 그냥 Return
if (m_isSoundDisable)
return;
// 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;
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);
m_isSoundDisable = false;
SetMusicVolume(m_fBackupMusicVolume);
SetSoundVolume(m_fBackupSoundVolume);
}
void CSoundManager::PlayMusic(DWORD dwIndex, const char * c_szFileName, float fVolume, float fVolumeSpeed)
float CSoundManager::GetSoundVolume()
{
if (dwIndex >= CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM)
return;
if (!ms_SoundManagerStream.SetInstance(dwIndex, c_szFileName))
{
TraceError("CSoundManager::PlayMusic - Failed to load stream sound : %s", c_szFileName);
return;
}
CSoundInstanceStream * pInstance = ms_SoundManagerStream.GetInstance(dwIndex);
if (!pInstance)
{
TraceError("CSoundManager::PlayMusic - There is no stream sound instance : %s", c_szFileName);
return;
}
pInstance->SetVolume(fVolume);
pInstance->Play(0);
TMusicInstance & rMusicInstance = m_MusicInstances[dwIndex];
rMusicInstance.fVolume = fVolume;
rMusicInstance.fVolumeSpeed = fVolumeSpeed;
rMusicInstance.MusicState = MUSIC_STATE_FADE_IN;
std::string strFileName;
StringPath(c_szFileName, strFileName);
rMusicInstance.dwMusicFileNameCRC = GetCaseCRC32(strFileName.c_str(), strFileName.length());
return m_fSoundVolume;
}
void CSoundManager::StopMusic(DWORD dwIndex)
float CSoundManager::GetMusicVolume()
{
if (dwIndex >= CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM)
return;
CSoundInstanceStream * pInstance = ms_SoundManagerStream.GetInstance(dwIndex);
if (!pInstance)
return;
pInstance->Stop();
TMusicInstance & rMusicInstance = m_MusicInstances[dwIndex];
rMusicInstance.fVolume = 0.0f;
rMusicInstance.fVolumeSpeed = 0.0f;
rMusicInstance.MusicState = MUSIC_STATE_OFF;
rMusicInstance.dwMusicFileNameCRC = 0;
return m_fMusicVolume;
}
BOOL CSoundManager::GetMusicIndex(const char * c_szFileName, DWORD * pdwIndex)
void CSoundManager::PlaySound2D(std::string_view filename)
{
std::string strFileName;
StringPath(c_szFileName, strFileName);
DWORD dwCRC = GetCaseCRC32(strFileName.c_str(), strFileName.length());
if (0.0f == GetSoundVolume())
return;
for (int i = 0; i < CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM; ++i)
{
const TMusicInstance & c_rMusicInstance = m_MusicInstances[i];
if (MUSIC_STATE_OFF != c_rMusicInstance.MusicState)
if (c_rMusicInstance.dwMusicFileNameCRC == dwCRC)
{
*pdwIndex = i;
return TRUE;
}
}
if (m_sounds2d.size() >= m_max2dSoundsPlaying)
return;
return FALSE;
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);
}
void CSoundManager::FadeAll()
float CSoundManager::__GetVolumeFromDistance(float fDistance)
{
FadeOutAllMusic();
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,111 +1,90 @@
#pragma once
#include "EterBase/Singleton.h"
#include "SampleFileCache.hpp"
#include "MusicInstance.hpp"
#include "SoundSample.hpp"
#include "../eterBase/Singleton.h"
#include <unordered_map>
#include "SoundManagerStream.h"
#include "SoundManager2D.h"
#include "SoundManager3D.h"
#include "Type.h"
struct MilesLibrary
{
MilesLibrary();
~MilesLibrary();
};
class CSoundManager : public CSingleton<CSoundManager>
{
public:
CSoundManager();
virtual ~CSoundManager();
CSoundManager();
BOOL Create();
void Destroy();
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();
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 SetSoundVolumeRatio(float fRatio);
void SetMusicVolume(float fVolume);
void SetMusicVolumeRatio(float fRatio);
void SetSoundVolumeGrade(int iGrade);
void SetMusicVolumeGrade(int iGrade);
void SaveVolume();
void RestoreVolume();
float GetSoundVolume();
float GetMusicVolume();
float GetSoundScale();
void SetSoundScale(float fScale);
void SetAmbienceSoundScale(float fScale);
// Sound
void PlaySound2D(const char * c_szFileName);
void PlaySound3D(float fx, float fy, float fz, const char * c_szFileName, int iPlayCount = 1);
void StopSound3D(int iIndex);
int PlayAmbienceSound3D(float fx, float fy, float fz, const char * c_szFileName, int iPlayCount = 1);
void PlayCharacterSound3D(float fx, float fy, float fz, const char * c_szFileName, BOOL bCheckFrequency = FALSE);
void SetSoundVolume3D(int iIndex, float fVolume);
void StopAllSound3D();
void SetSoundVolume(float fVolume);
void SetMusicVolume(float fVolume);
// Music
void PlayMusic(const char * c_szFileName);
void FadeInMusic(const char * c_szFileName, float fVolumeSpeed = 0.016f);
void FadeOutMusic(const char * c_szFileName, float fVolumeSpeed = 0.016f);
void FadeLimitOutMusic(const char * c_szFileName, float fLimitVolume, float fVolumeSpeed = 0.016f);
void FadeOutAllMusic();
void FadeAll();
void SaveVolume();
void RestoreVolume();
// Sound Node
void UpdateSoundData(DWORD dwcurFrame, const NSound::TSoundDataVector * c_pSoundDataVector);
void UpdateSoundData(float fx, float fy, float fz, DWORD dwcurFrame, const NSound::TSoundDataVector * c_pSoundDataVector);
void UpdateSoundInstance(float fx, float fy, float fz, DWORD dwcurFrame, const NSound::TSoundInstanceVector * c_pSoundInstanceVector, BOOL bCheckFrequency = FALSE);
void UpdateSoundInstance(DWORD dwcurFrame, const NSound::TSoundInstanceVector * c_pSoundInstanceVector);
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:
enum EMusicState
{
MUSIC_STATE_OFF,
MUSIC_STATE_PLAY,
MUSIC_STATE_FADE_IN,
MUSIC_STATE_FADE_OUT,
MUSIC_STATE_FADE_LIMIT_OUT,
};
typedef struct SMusicInstance
{
DWORD dwMusicFileNameCRC;
EMusicState MusicState;
float fVolume;
float fLimitVolume;
float fVolumeSpeed;
} TMusicInstance;
MilesLibrary m_miles;
bool m_isSoundDisable;
void PlayMusic(DWORD dwIndex, const char * c_szFileName, float fVolume, float fVolumeSpeed);
void StopMusic(DWORD dwIndex);
BOOL GetMusicIndex(const char * c_szFileName, DWORD * pdwIndex);
uint32_t m_max2dSoundsPlaying;
uint32_t m_max3dSoundsPlaying;
uint32_t m_maxMusicPlaying;
protected:
float __ConvertGradeVolumeToApplyVolume(int nVolumeGrade);
float __ConvertRatioVolumeToApplyVolume(float fVolumeRatio);
void __SetMusicVolume(float fVolume);
BOOL GetSoundInstance2D(const char * c_szSoundFileName, ISoundInstance ** ppInstance);
BOOL GetSoundInstance3D(const char * c_szFileName, ISoundInstance ** ppInstance);
float m_fxPosition;
float m_fyPosition;
float m_fzPosition;
protected:
BOOL m_bInitialized;
BOOL m_isSoundDisable;
float m_fSoundScale;
float m_fAmbienceSoundScale;
float m_fSoundVolume;
float m_fMusicVolume;
float m_fxPosition;
float m_fyPosition;
float m_fzPosition;
float m_fBackupMusicVolume;
float m_fBackupSoundVolume;
float m_fSoundScale;
float m_fAmbienceSoundScale;
float m_fSoundVolume;
float m_fMusicVolume;
HDIGDRIVER m_driver;
float m_fBackupMusicVolume;
float m_fBackupSoundVolume;
TMusicInstance m_MusicInstances[CSoundManagerStream::MUSIC_INSTANCE_MAX_NUM];
std::map<std::string, float> m_PlaySoundHistoryMap;
static CSoundManager2D ms_SoundManager2D;
static CSoundManager3D ms_SoundManager3D;
static CSoundManagerStream ms_SoundManagerStream;
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,79 +0,0 @@
#include "Stdafx.h"
#include "SoundManager2D.h"
CSoundManager2D::CSoundManager2D()
{
}
CSoundManager2D::~CSoundManager2D()
{
}
bool CSoundManager2D::Initialize()
{
CSoundBase::Initialize();
if (ms_DIGDriver)
return true;
ms_DIGDriver = AIL_open_digital_driver(44100, 16, 2, 0);
for (int i = 0; i < INSTANCE_MAX_COUNT; ++i)
ms_Instances[i].Initialize();
/* ms_DIGDriver = AIL_open_digital_driver(44100,
(DIG_F_STEREO_16 & DIG_F_16BITS_MASK) ? 16 : 8,
(DIG_F_STEREO_16 & DIG_F_16BITS_MASK) ? 2 : 1,
0);
*/
return true;
}
void CSoundManager2D::Destroy()
{
for (int i = 0; i < INSTANCE_MAX_COUNT; ++i)
ms_Instances[i].Destroy();
if (ms_DIGDriver != NULL)
{
AIL_close_digital_driver(ms_DIGDriver);
ms_DIGDriver = NULL;
}
CSoundBase::Destroy();
}
ISoundInstance * CSoundManager2D::GetInstance(const char * c_pszFileName)
{
DWORD dwFileCRC = GetFileCRC(c_pszFileName);
TSoundDataMap::iterator itor = ms_dataMap.find(dwFileCRC);
CSoundData * pkSoundData;
if (itor == ms_dataMap.end())
pkSoundData = AddFile(dwFileCRC, c_pszFileName); // CSoundBase::AddFile
else
pkSoundData = itor->second;
assert(pkSoundData != NULL);
static DWORD k = 0;
DWORD start = k++;
DWORD end = start + INSTANCE_MAX_COUNT;
while (start < end)
{
CSoundInstance2D * pkInst = &ms_Instances[start % INSTANCE_MAX_COUNT];
if (pkInst->IsDone())
{
if (!pkInst->SetSound(pkSoundData))
TraceError("CSoundManager2D::GetInstance (filename: %s)", c_pszFileName);
return (pkInst);
}
++start;
}
return NULL;
}

View File

@@ -1,27 +0,0 @@
#ifndef __MILESLIB_CSOUNDMANAGER2D_H__
#define __MILESLIB_CSOUNDMANAGER2D_H__
#include "SoundBase.h"
#include "SoundInstance.h"
class CSoundManager2D : public CSoundBase
{
public:
enum
{
INSTANCE_MAX_COUNT = 4
};
CSoundManager2D();
virtual ~CSoundManager2D();
bool Initialize();
void Destroy();
ISoundInstance * GetInstance(const char* filename);
protected:
CSoundInstance2D ms_Instances[INSTANCE_MAX_COUNT];
};
#endif

View File

@@ -1,205 +0,0 @@
#include "Stdafx.h"
#include "SoundManager3D.h"
CSoundManager3D::CSoundManager3D()
{
m_bInit = false;
}
CSoundManager3D::~CSoundManager3D()
{
}
bool CSoundManager3D::Initialize()
{
CSoundBase::Initialize();
if (ms_pProviderDefault)
return true;
ms_ProviderVector.resize(MAX_PROVIDERS);
HPROENUM enum3D = HPROENUM_FIRST;
int i = 0;
while (AIL_enumerate_3D_providers(&enum3D,
&ms_ProviderVector[i].hProvider,
&ms_ProviderVector[i].name) && (i < MAX_PROVIDERS))
{
TProvider * provider = &ms_ProviderVector[i];
//if (strcmp(provider->name, "DirectSound3D Software Emulation") == 0)
//if (strcmp(provider->name, "DirectSound3D Hardware Support") == 0)
//if (strcmp(provider->name, "DirectSound3D 7+ Software - Pan and Volume") == 0)
//if (strcmp(provider->name, "DirectSound3D 7+ Software - Light HRTF") == 0)
//if (strcmp(provider->name, "DirectSound3D 7+ Software - Full HRTF") == 0)
//if (strcmp(provider->name, "RAD Game Tools RSX 3D Audio") == 0)
//if (strcmp(provider->name, "Dolby Surround") == 0)
if (strcmp(provider->name, "Miles Fast 2D Positional Audio") == 0)
ms_pProviderDefault = provider;
++i;
}
if (!ms_pProviderDefault)
{
CSoundBase::Destroy();
return false;
}
assert(ms_pProviderDefault != NULL);
if (M3D_NOERR != AIL_open_3D_provider(ms_pProviderDefault->hProvider))
{
// assert(!"AIL_open_3D_provider error");
// char buf[64];
// sprintf(buf, "Error AIL_open_3D_provider: %s\n", AIL_last_error());
// OutputDebugString(buf);
CSoundBase::Destroy();
return false;
}
m_pListener = AIL_open_3D_listener(ms_pProviderDefault->hProvider);
SetListenerPosition(0.0f, 0.0f, 0.0f);
for (i = 0; i < INSTANCE_MAX_COUNT; ++i)
{
m_Instances[i].Initialize();
m_bLockingFlag[i] = false;
}
m_bInit = true;
return true;
}
void CSoundManager3D::Destroy()
{
if (!m_bInit)
return;
for (int i = 0; i < INSTANCE_MAX_COUNT; ++i)
m_Instances[i].Destroy();
if (m_pListener)
{
AIL_close_3D_listener(m_pListener);
m_pListener = NULL;
}
if (ms_pProviderDefault)
{
AIL_close_3D_provider(ms_pProviderDefault->hProvider);
ms_pProviderDefault = NULL;
}
CSoundBase::Destroy();
m_bInit = false;
}
void CSoundManager3D::SetListenerDirection(float fxDir, float fyDir, float fzDir, float fxUp, float fyUp, float fzUp)
{
if (NULL == m_pListener)
return;
AIL_set_3D_orientation(m_pListener, fxDir, fyDir, -fzDir, fxUp, fyUp, -fzUp);
}
void CSoundManager3D::SetListenerPosition(float fX, float fY, float fZ)
{
// assert(m_pListener != NULL);
if (NULL == m_pListener)
return;
AIL_set_3D_position(m_pListener, fX, fY, -fZ);
}
void CSoundManager3D::SetListenerVelocity(float fDistanceX, float fDistanceY, float fDistanceZ, float fNagnitude)
{
// assert(m_pListener != NULL);
if (NULL == m_pListener)
return;
AIL_set_3D_velocity(m_pListener, fDistanceX, fDistanceY, -fDistanceZ, fNagnitude);
}
int CSoundManager3D::SetInstance(const char * c_pszFileName)
{
DWORD dwFileCRC = GetFileCRC(c_pszFileName);
TSoundDataMap::iterator itor = ms_dataMap.find(dwFileCRC);
CSoundData * pkSoundData;
if (itor == ms_dataMap.end())
pkSoundData = AddFile(dwFileCRC, c_pszFileName); // CSoundBase::AddFile
else
pkSoundData = itor->second;
assert(pkSoundData != NULL);
static DWORD k = 0;
DWORD start = k++;
DWORD end = start + INSTANCE_MAX_COUNT;
while (start < end)
{
CSoundInstance3D * pkInst = &m_Instances[start % INSTANCE_MAX_COUNT];
if (pkInst->IsDone())
{
if (!pkInst->SetSound(pkSoundData))
{
TraceError("CSoundManager3D::GetInstance (filename: %s)", c_pszFileName);
// NOTE : 사운드가 없을 경우 Failed to set. return NULL. - [levites]
return -1;
}
return (start % INSTANCE_MAX_COUNT);
}
++start;
// 설마 DWORD 한계값을 넘어갈리야 없겠지만.. 그래도.. 혹시나.. - [levites]
if (start > 50000)
{
start = 0;
return -1;
}
}
return -1;
}
ISoundInstance * CSoundManager3D::GetInstance(DWORD dwIndex)
{
if (dwIndex >= INSTANCE_MAX_COUNT)
{
assert(dwIndex < INSTANCE_MAX_COUNT);
return NULL;
}
return &m_Instances[dwIndex];
}
__forceinline bool CSoundManager3D::IsValidInstanceIndex(int iIndex)
{
if (iIndex >= 0 && iIndex < INSTANCE_MAX_COUNT)
return true;
return false;
}
void CSoundManager3D::Lock(int iIndex)
{
if (!IsValidInstanceIndex(iIndex))
return;
m_bLockingFlag[iIndex] = true;
}
void CSoundManager3D::Unlock(int iIndex)
{
if (!IsValidInstanceIndex(iIndex))
return;
m_bLockingFlag[iIndex] = false;
}

View File

@@ -1,45 +0,0 @@
#ifndef __MILESLIB_CSOUNDMANAGER3D_H__
#define __MILESLIB_CSOUNDMANAGER3D_H__
#include "SoundBase.h"
#include "SoundInstance.h"
class CSoundManager3D : public CSoundBase
{
public:
enum
{
INSTANCE_MAX_COUNT = 32,
MAX_PROVIDERS = 32,
};
public:
CSoundManager3D();
virtual ~CSoundManager3D();
bool Initialize();
void Destroy();
int GetEmptyInstanceIndex();
int SetInstance(const char * c_szFileName);
ISoundInstance * GetInstance(DWORD dwIndex);
void SetListenerDirection(float fxDir, float fyDir, float fzDir, float fxUp, float fyUp, float fzUp);
void SetListenerPosition(float x, float y, float z);
void SetListenerVelocity(float fDistanceX, float fDistanceY, float fDistanceZ, float fNagnitude);
void Lock(int iIndex);
void Unlock(int iIndex);
protected:
bool IsValidInstanceIndex(int iIndex);
protected:
bool m_bLockingFlag[INSTANCE_MAX_COUNT];
CSoundInstance3D m_Instances[INSTANCE_MAX_COUNT];
H3DPOBJECT m_pListener;
bool m_bInit;
};
#endif

View File

@@ -1,64 +0,0 @@
#include "stdafx.h"
#include "SoundManagerStream.h"
CSoundManagerStream::CSoundManagerStream()
{
}
CSoundManagerStream::~CSoundManagerStream()
{
}
bool CSoundManagerStream::Initialize()
{
CSoundBase::Initialize();
if (ms_DIGDriver)
return true;
ms_DIGDriver = AIL_open_digital_driver(44100, 16, 2, 0);
for (int i = 0; i < MUSIC_INSTANCE_MAX_NUM; ++i)
m_Instances[i].Initialize();
return true;
}
void CSoundManagerStream::Destroy()
{
for (int i=0; i<MUSIC_INSTANCE_MAX_NUM; ++i)
m_Instances[i].Stop();
CSoundBase::Destroy();
}
bool CSoundManagerStream::SetInstance(DWORD dwIndex, const char* filename)
{
if (!CheckInstanceIndex(dwIndex))
return false;
HSTREAM hStream = AIL_open_stream(ms_DIGDriver, filename, 0);
if (NULL == hStream)
return false;
m_Instances[dwIndex].SetStream(hStream);
return true;
}
CSoundInstanceStream * CSoundManagerStream::GetInstance(DWORD dwIndex)
{
if (!CheckInstanceIndex(dwIndex))
return NULL;
return &m_Instances[dwIndex];
}
bool CSoundManagerStream::CheckInstanceIndex(DWORD dwIndex)
{
if (dwIndex >= DWORD(MUSIC_INSTANCE_MAX_NUM))
return false;
return true;
}

View File

@@ -1,32 +0,0 @@
#ifndef __MILESLIB_CSOUNDMANAGERSTREAM_H__
#define __MILESLIB_CSOUNDMANAGERSTREAM_H__
#include "SoundBase.h"
#include "SoundInstance.h"
class CSoundManagerStream : public CSoundBase
{
public:
enum
{
MUSIC_INSTANCE_MAX_NUM = 3,
};
public:
CSoundManagerStream();
virtual ~CSoundManagerStream();
bool Initialize();
void Destroy();
bool SetInstance(DWORD dwIndex, const char* filename);
CSoundInstanceStream * GetInstance(DWORD dwIndex);
protected:
bool CheckInstanceIndex(DWORD dwIndex);
protected:
CSoundInstanceStream m_Instances[MUSIC_INSTANCE_MAX_NUM];
};
#endif

View File

@@ -0,0 +1,108 @@
#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

@@ -0,0 +1,35 @@
#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

@@ -0,0 +1,66 @@
#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

@@ -0,0 +1,25 @@
#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,2 +1 @@
#include "stdafx.h"

View File

@@ -1,35 +1,5 @@
#ifndef __INC_MILESLIB_STDAFX_H__
#define __INC_MILESLIB_STDAFX_H__
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#pragma warning(disable:4786)
#pragma warning(disable:4100)
#include "EterBase/StdAfx.h"
#pragma warning(disable:4201)
#pragma warning(default:4201)
#include <windows.h>
//#include <crtdbg.h>
#include "../eterBase/CRC32.h"
#include "../eterBase/Utils.h"
#include "../eterBase/Debug.h"
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
// Armadillo nanomite protection
#ifndef NANOBEGIN
#ifdef __BORLANDC__
#define NANOBEGIN __emit__ (0xEB,0x03,0xD6,0xD7,0x01)
#define NANOEND __emit__ (0xEB,0x03,0xD6,0xD7,0x00)
#else
#define NANOBEGIN __asm _emit 0xEB __asm _emit 0x03 __asm _emit 0xD6 __asm _emit 0xD7 __asm _emit 0x01
#define NANOEND __asm _emit 0xEB __asm _emit 0x03 __asm _emit 0xD6 __asm _emit 0xD7 __asm _emit 0x00
#endif
#endif
#endif
#include <mss.h>

View File

@@ -1,136 +1,150 @@
#include "StdAfx.h"
#include "Stdafx.h"
#include "Type.h"
#include "SoundManager.h"
#include "../EterBase/Debug.h"
#include "../EterLib/TextFileLoader.h"
#include "../EterLib/Util.h"
std::string NSound::strResult;
const char * NSound::GetResultString()
bool LoadSoundInformationPiece(const char *c_szFileName,
TSoundDataVector &rSoundDataVector,
const char *c_szPathHeader)
{
return strResult.c_str();
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;
}
void NSound::SetResultString(const char * c_pszStr)
bool SaveSoundInformationPiece(const char *c_szFileName, TSoundDataVector &rSoundDataVector)
{
strResult.assign(c_pszStr);
/*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;
}
bool NSound::LoadSoundInformationPiece(const char * c_szFileName, NSound::TSoundDataVector & rSoundDataVector, const char * c_szPathHeader)
void DataToInstance(const TSoundDataVector &c_rSoundDataVector, TSoundInstanceVector *pSoundInstanceVector)
{
std::string strResult;
strResult = c_szFileName;
if (c_rSoundDataVector.empty())
return;
CTextFileLoader* pkTextFileLoader=CTextFileLoader::Cache(c_szFileName);
if (!pkTextFileLoader)
return false;
const float c_fFrameTime = 1.0f / 60.0f;
CTextFileLoader& rkTextFileLoader=*pkTextFileLoader;
if (rkTextFileLoader.IsEmpty())
{
SetResultString((strResult + " 읽기용 파일을 열 수 없음").c_str());
return false;
}
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);
rkTextFileLoader.SetTop();
int iCount;
if (!rkTextFileLoader.GetTokenInteger("sounddatacount", &iCount))
{
SetResultString((strResult + " 파일 포멧 에러, SoundDataCount를 찾을 수 없음").c_str());
return false;
}
rSoundDataVector.clear();
rSoundDataVector.resize(iCount);
char szSoundDataHeader[32+1];
for (DWORD i = 0; i < rSoundDataVector.size(); ++i)
{
_snprintf(szSoundDataHeader, sizeof(szSoundDataHeader), "sounddata%02d", i);
CTokenVector * pTokenVector;
if (!rkTextFileLoader.GetTokenVector(szSoundDataHeader, &pTokenVector))
{
SetResultString((strResult + " 파일 포멧 에러: " + szSoundDataHeader + " 를 찾을 수 없음").c_str());
return false;
}
if (2 != pTokenVector->size())
{
SetResultString((strResult + " 파일 포멧 에러: 벡터 크기가 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();
}
}
SetResultString((strResult + " 불러옴").c_str());
return true;
rSoundInstance.dwFrame = (uint32_t)(c_rSoundData.fTime / c_fFrameTime);
rSoundInstance.strSoundFileName = c_rSoundData.strSoundFileName;
}
}
bool NSound::SaveSoundInformationPiece(const char * c_szFileName, NSound::TSoundDataVector & rSoundDataVector)
void UpdateSoundInstance(uint32_t frame, const TSoundInstanceVector &sounds,
float fx, float fy, float fz, bool bCheckFrequency)
{
if (rSoundDataVector.empty()) // 데이터가 없으면 성공으로 간주
{
if (IsFile(c_szFileName)) // 데이터는 비어있는데 파일이 있다면
{
_unlink(c_szFileName); // 지운다.
}
return true;
}
auto &snd = CSoundManager::Instance();
for (const auto &instance : sounds)
{
if (instance.dwFrame != frame)
continue;
std::string strResult;
strResult = c_szFileName;
FILE * File = fopen(c_szFileName, "wt");
if (!File)
{
char szErrorText[256+1];
_snprintf(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, "에러");
SetResultString((strResult + " 쓰기용 파일을 열 수 없음").c_str());
return false;
}
fprintf(File, "ScriptType CharacterSoundInformation\n");
fprintf(File, "\n");
fprintf(File, "SoundDataCount %d\n", rSoundDataVector.size());
for (DWORD 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;
snd.PlayCharacterSound3D(fx, fy, fz,
instance.strSoundFileName,
bCheckFrequency);
}
}
void NSound::DataToInstance(const TSoundDataVector & c_rSoundDataVector, TSoundInstanceVector * pSoundInstanceVector)
void UpdateSoundInstance(uint32_t frame, const TSoundInstanceVector &sounds)
{
if (c_rSoundDataVector.empty())
return;
DWORD dwFPS = 60;
const float c_fFrameTime = 1.0f / float(dwFPS);
pSoundInstanceVector->clear();
pSoundInstanceVector->resize(c_rSoundDataVector.size());
for (DWORD i = 0; i < c_rSoundDataVector.size(); ++i)
{
const TSoundData & c_rSoundData = c_rSoundDataVector[i];
TSoundInstance & rSoundInstance = pSoundInstanceVector->at(i);
rSoundInstance.dwFrame = (DWORD) (c_rSoundData.fTime / c_fFrameTime);
rSoundInstance.strSoundFileName = c_rSoundData.strSoundFileName;
}
}
for (const auto &instance : sounds)
{
if (instance.dwFrame == frame)
CSoundManager::Instance().PlaySound2D(instance.strSoundFileName);
}
}

View File

@@ -1,28 +1,37 @@
#ifndef METIN2_CLIENT_MILESLIB_TYPE_HPP
#define METIN2_CLIENT_MILESLIB_TYPE_HPP
#pragma once
#include <vector>
namespace NSound
typedef struct SSoundData
{
extern std::string strResult;
float fTime;
std::string strSoundFileName;
} TSoundData;
typedef struct SSoundData
{
float fTime;
std::string strSoundFileName;
} TSoundData;
typedef struct SSoundInstance
{
DWORD dwFrame;
std::string strSoundFileName;
} TSoundInstance;
typedef std::vector<TSoundData> TSoundDataVector;
typedef std::vector<TSoundInstance> TSoundInstanceVector;
typedef struct SSoundInstance
{
uint32_t dwFrame;
std::string strSoundFileName;
} TSoundInstance;
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);
typedef std::vector<TSoundData> TSoundDataVector;
typedef std::vector<TSoundInstance> TSoundInstanceVector;
const char * GetResultString();
void SetResultString(const char * c_pszStr);
};
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