Import of more nw4r::snd from https://github.com/kiwi515/ogws

Co-authored-by: kiwi515 <49212064+kiwi515@users.noreply.github.com>
This commit is contained in:
robojumper
2025-05-25 16:29:42 +02:00
parent b5c3d85ea2
commit f7884242c7
40 changed files with 2076 additions and 74 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
# Ignore JSystem Files - Copied From TP
**/JSystem/**
# Ignore SND Files - Copied from https://github.com/muff1n1634/nw4r_snd_mid2010
# Ignore SND Files - Copied from https://github.com/muff1n1634/nw4r_snd_mid2010, https://github.com/kiwi515/ogws
**/nw4r/snd/**
+2 -2
View File
@@ -25202,7 +25202,7 @@ __ct__Q34nw4r3snd15DvdSoundArchiveFv = .text:0x8046BB60; // type:function size:0
__dt__Q34nw4r3snd15DvdSoundArchiveFv = .text:0x8046BBB0; // type:function size:0x8C
Open__Q34nw4r3snd15DvdSoundArchiveFPCc = .text:0x8046BC40; // type:function size:0x14C
Close__Q34nw4r3snd15DvdSoundArchiveFv = .text:0x8046BD90; // type:function size:0x4C
fn_8046BDE0 = .text:0x8046BDE0; // type:function size:0xA8
OpenStream__Q34nw4r3snd15DvdSoundArchiveCFPviUlUl = .text:0x8046BDE0; // type:function size:0xA8
OpenExtStream__Q34nw4r3snd15DvdSoundArchiveCFPviPCcUlUl = .text:0x8046BE90; // type:function size:0xB8
detail_GetRequiredStreamBufferSize__Q34nw4r3snd15DvdSoundArchiveCFv = .text:0x8046BF50; // type:function size:0x8
LoadHeader__Q34nw4r3snd15DvdSoundArchiveFPvUl = .text:0x8046BF60; // type:function size:0x88
@@ -25241,7 +25241,7 @@ Alloc__Q44nw4r3snd6detail9FrameHeapFUlPFPvUlPv_vPv = .text:0x8046CEE0; // type:f
SaveState__Q44nw4r3snd6detail9FrameHeapFv = .text:0x8046CF90; // type:function size:0xCC
LoadState__Q44nw4r3snd6detail9FrameHeapFi = .text:0x8046D060; // type:function size:0x224
GetCurrentLevel__Q44nw4r3snd6detail9FrameHeapCFv = .text:0x8046D290; // type:function size:0xC
FUN_8046d2a0 = .text:0x8046D2A0; // type:function size:0x40
GetFreeSize__Q44nw4r3snd6detail9FrameHeapCFv = .text:0x8046D2A0; // type:function size:0x40
__ct__Q34nw4r3snd15FxReverbStdDpl2Fv = .text:0x8046D2E0; // type:function size:0xC4
GetRequiredMemSize__Q34nw4r3snd15FxReverbStdDpl2Fv = .text:0x8046D3B0; // type:function size:0x54
AssignWorkBuffer__Q34nw4r3snd15FxReverbStdDpl2FPvUl = .text:0x8046D410; // type:function size:0x8
+7 -1
View File
@@ -102,12 +102,18 @@ namespace nw4r { namespace snd { namespace detail
void SetMasterVolume(f32 volume, int frame);
void PrepareReset();
bool IsResetReady() const {
return mResetReadyCounter == 0;
}
private:
// cdtors
AxManager();
// callbacks
static void AxCallbackFunc();
static void AuxCallbackFunc(void* pChans, void* pContext);
static void AiDmaCallbackFunc();
// static members
private:
@@ -140,7 +146,7 @@ namespace nw4r { namespace snd { namespace detail
MoveValue<f32, int> mMasterVolume; // size 0x10, offset 0x1c
MoveValue<f32, int> mMainOutVolume; // size 0x10, offset 0x2c
MoveValue<f32, int> mVolumeForReset; // size 0x10, offset 0x3c
AIDMACallback *mOldAidCallback; // size 0x04, offset 0x4c
AIDMACallback mOldAidCallback; // size 0x04, offset 0x4c
s32 mResetReadyCounter; // size 0x04, offset 0x50
MoveValue<f32, int> mAuxFadeVolume[AUX_BUS_NUM]; // size 0x30, offset 0x54
MoveValue<f32, int> mAuxUserVolume[AUX_BUS_NUM]; // size 0x30, offset 0x84
+3
View File
@@ -47,6 +47,9 @@ namespace nw4r { namespace snd { namespace detail
// static members
public:
static int const VOICE_COUNT_MARGIN = 16;
static const int VOICE_MARGIN = 16;
static const int VOICE_MAX = AX_VOICE_MAX + VOICE_MARGIN;
static const int WORK_SIZE_MAX = VOICE_MAX * sizeof(AxVoice);
// members
private:
+7
View File
@@ -156,6 +156,13 @@ namespace nw4r { namespace snd { namespace detail
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x276d8
class AmbientParamUpdateCallback
{
public:
enum ParamUpdateFlags {
PARAM_UPDATE_VOLUME = (1 << 0),
PARAM_UPDATE_PAN = (1 << 1),
PARAM_UPDATE_SURROUND_PAN = (1 << 2),
PARAM_UPDATE_PRIORITY = (1 << 3),
};
// methods
public:
virtual void at_0x08();
+4
View File
@@ -242,6 +242,10 @@ namespace nw4r { namespace snd { namespace detail
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2b895c
class ChannelManager
{
public:
static const int VOICE_MARGIN = 1;
static const int VOICE_MAX = AX_VOICE_MAX + VOICE_MARGIN;
static const int WORK_SIZE_MAX = VOICE_MAX * sizeof(Channel);
// methods
public:
// instance accessors
-32
View File
@@ -9,38 +9,6 @@ namespace nw4r {
namespace snd {
namespace detail {
class ChannelManager {
friend class Channel; // Alloc/Free intended through Channel only
public:
static const int VOICE_MARGIN = 1;
static const int VOICE_MAX = AX_VOICE_MAX + VOICE_MARGIN;
static const int WORK_SIZE_MAX = VOICE_MAX * sizeof(Channel);
public:
static ChannelManager &GetInstance();
u32 GetRequiredMemSize();
void Setup(void *pWork, u32 workSize);
void Shutdown();
void UpdateAllChannel();
private:
ChannelManager();
Channel *Alloc();
void Free(Channel *pChannel);
private:
InstancePool<Channel> mPool; // at 0x0
ChannelList mChannelList; // at 0x4
bool mInitialized; // at 0x10
u32 mChannelCount; // at 0x14
void *mMem; // at 0x18
u32 mMemSize; // at 0x1C
};
} // namespace detail
} // namespace snd
} // namespace nw4r
-23
View File
@@ -70,29 +70,6 @@ namespace nw4r { namespace snd
DVDFileInfo mFileInfo; // at 0x14C
bool mOpen; // at 0x188
};
class DvdSoundArchive::DvdFileStream : public ut::FileStream
{
DvdFileStream();
virtual ut::detail::RuntimeTypeInfo const *GetRuntimeTypeInfo() const { return 0; }
virtual void Close() {}
virtual s32 Read(void *, u32) { return 0; }
virtual bool IsBusy() const { return 0; }
virtual bool CanAsync() const { return 0; }
virtual bool CanRead() const { return 0; }
virtual bool CanWrite() const { return 0; }
virtual u32 GetOffsetAlign() const { return 0; }
virtual u32 GetSizeAlign() const { return 0; }
virtual u32 GetBufferAlign() const { return 0; }
virtual u32 GetSize() const { return 0; }
virtual void Seek(s32, u32) {}
virtual void Cancel() {}
virtual bool CancelAsync(StreamCallback *, void *) { return 0; }
virtual bool CanSeek() const { return 0; }
virtual bool CanCancel() const { return 0; }
virtual u32 Tell() const { return 0; }
friend class DvdSoundArchive;
};
}} // namespace nw4r::snd
#endif // NW4R_SND_DVD_SOUND_ARCHIVE_H
@@ -19,8 +19,11 @@ namespace nw4r { namespace snd { namespace detail
// methods
public:
// methods
ExternalSoundPlayer();
~ExternalSoundPlayer();
int GetPlayingSoundCount() const { return mSoundList.GetSize(); }
int GetPlayableSoundCount() const { return mPlayableCount; }
void SetPlayableSoundCount(int count);
bool AppendSound(BasicSound *sound);
void RemoveSound(BasicSound *sound);
+4 -4
View File
@@ -76,17 +76,17 @@ private:
bool mFirstEncodeFlag; // at 0x3
bool mValidCallbackFlag; // at 0x4
bool mCommandBusyFlag; // at 0x5
bool mForceResumeFlag; // at 0x6
bool mContinueFlag; // at 0x7
// TODO commenting out a random flag to make eggAudioRmtSpeakerMgr match
// TODO offsets are wrong as a result
// volatile bool mIntervalFlag; // at 0x8
// bool mForceResumeFlag; // at 0x6
bool mContinueFlag; // at 0x7
volatile bool mIntervalFlag; // at 0x8
SpeakerState mState; // at 0xC
SpeakerCommand mUserCommand; // at 0x10
SpeakerCommand mInternalCommand; // at 0x14
WENCInfo mEncodeInfo; // at 0x18
int mChannelIndex; // at 0x38
WPADCallback mWpadCallback; // at 0x3C
WPADCallback *mWpadCallback; // at 0x3C
OSAlarm mContinueAlarm; // at 0x40
OSAlarm mIntervalAlarm; // at 0x70
s64 mContinueBeginTime; // at 0xA0
+1 -1
View File
@@ -21,7 +21,7 @@ public:
private:
static const int SPEAKER_ALARM_HZ = 150;
// static const int SPEAKER_ALARM_PERIOD_NSEC = 1.0f / SPEAKER_ALARM_HZ * 1000 * 1000 * 1000;
static const int SPEAKER_ALARM_PERIOD_NSEC = static_cast<int>(1.0f / SPEAKER_ALARM_HZ * 1000 * 1000 * 1000);
private:
RemoteSpeakerManager();
+1
View File
@@ -128,6 +128,7 @@ namespace nw4r { namespace snd { namespace detail
SeqTrack *GetPlayerTrack(int trackNo);
s16 volatile *GetVariablePtr(int varNo);
void SetTempoRatio(f32 tempo);
void SetReleasePriorityFix(bool fix);
void SetChannelPriority(int priority);
void SetSeqUserprocCallback(SeqUserprocCallback *callback, void *arg);
+1
View File
@@ -108,6 +108,7 @@ namespace nw4r { namespace snd { namespace detail
s32 GetFileStreamBufferSize() { return sizeof mFileStreamBuffer; }
void SetReleasePriorityFix(bool fix);
void SetTempoRatio(f32 tempo);
void SetChannelPriority(int priority);
void SetSeqUserprocCallback(SeqPlayer::SeqUserprocCallback *callback,
void *arg);
+1 -1
View File
@@ -15,7 +15,7 @@ class Sound3DManager : public detail::BasicSound::AmbientInfo::AmbientParamUpdat
public:
struct Sound3DActorParam {
u32 userParam; // at 0x0
SoundParam soundParam; // at 0x4
SoundArchive::Sound3DParam soundParam; // at 0x4
math::VEC3 position; // at 0xC
Sound3DActorParam();
+16
View File
@@ -119,6 +119,12 @@ namespace nw4r { namespace snd
/* 3 bytes padding */
}; // size 0x0c
struct Sound3DParam {
u32 flags; // at 0x0
u8 decayCurve; // at 0x4
u8 decayRatio; // at 0x5
};
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x256dc
struct SoundArchivePlayerInfo
{
@@ -170,7 +176,11 @@ namespace nw4r { namespace snd
bool IsAvailable() const;
SoundType GetSoundType(u32 soundId) const;
const char* GetSoundLabelString(u32 id) const;
u32 ConvertLabelStringToSoundId(char const *label) const;
u32 ConvertLabelStringToPlayerId(const char* pLabel) const;
u32 ConvertLabelStringToGroupId(const char* pLabel) const;
u32 GetSoundUserParam(u32 id) const;
bool ReadSoundInfo(u32 soundId, SoundInfo *info) const;
bool ReadSeqSoundInfo(u32 soundId, SeqSoundInfo *info) const;
@@ -192,6 +202,12 @@ namespace nw4r { namespace snd
ut::FileStream *detail_OpenFileStream(u32 fileId, void *buffer,
int size) const;
ut::FileStream* detail_OpenGroupStream(u32 id, void* pBuffer,
int bufferSize) const;
ut::FileStream* detail_OpenGroupWaveDataStream(u32 id, void* pBuffer,
int bufferSize) const;
void SetExternalFileRoot(const char* pExtFileRoot);
private:
ut::FileStream *OpenExtStreamImpl(void *buffer, int size,
+13 -3
View File
@@ -35,6 +35,8 @@ namespace nw4r { namespace snd { namespace detail
u32 fileImageSize; // size 0x04, offset 0x24
}; // size 0x28
static const int HEADER_AREA_SIZE = ROUND_UP(sizeof(Header), 32) + 40;
/* SymbolBlock */
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x24881
@@ -332,9 +334,17 @@ namespace nw4r { namespace snd { namespace detail
u32 ConvertLabelStringToId(SoundArchiveFile::StringTree const *tree,
char const *str) const;
u32 ConvertLabelStringToSoundId(char const *label) const
{
return ConvertLabelStringToId(mStringTreeSound, label);
const char* GetSoundLabelString(u32 id) const;
u32 GetSoundUserParam(u32 id) const;
u32 ConvertLabelStringToSoundId(const char* pLabel) const {
return ConvertLabelStringToId(mStringTreeSound, pLabel);
}
u32 ConvertLabelStringToPlayerId(const char* pLabel) const {
return ConvertLabelStringToId(mStringTreePlayer, pLabel);
}
u32 ConvertLabelStringToGroupId(const char* pLabel) const {
return ConvertLabelStringToId(mStringTreeGroup, pLabel);
}
private:
@@ -184,7 +184,9 @@ namespace nw4r { namespace snd
u32 GetRequiredMemSize(SoundArchive const *arc);
u32 GetRequiredStrmBufferSize(SoundArchive const *arc);
void const *GetGroupAddress(u32 groupId) const;
void SetGroupAddress(u32 id, const void* pAddr);
void const *GetGroupWaveDataAddress(u32 groupId) const;
void SetGroupWaveDataAddress(u32 id, const void* pAddr);
void const *GetFileAddress(u32 fileId) const;
void const *GetFileWaveDataAddress(u32 fileId) const;
void const *detail_GetFileAddress(u32 fileId) const;
+1
View File
@@ -27,6 +27,7 @@ namespace nw4r { namespace snd
~SoundHandle() { DetachSound(); }
// methods
void detail_AttachSoundAsTempHandle(detail::BasicSound* pSound);
void detail_AttachSound(detail::BasicSound *sound);
bool IsAttachedSound() const { return mSound != nullptr; }
detail::BasicSound *detail_GetAttachedSound() { return mSound; }
+11
View File
@@ -42,6 +42,17 @@ namespace nw4r { namespace snd { namespace detail
CALLBACK_STATUS_DROP_DSP,
};
enum VoiceSyncFlag {
SYNC_AX_SRC_INITIAL = (1 << 0),
SYNC_AX_VOICE = (1 << 1),
SYNC_AX_SRC = (1 << 2),
SYNC_AX_VE = (1 << 3),
SYNC_AX_MIX = (1 << 4),
SYNC_AX_LPF = (1 << 5),
SYNC_AX_REMOTE = (1 << 7),
SYNC_AX_BIQUAD = (1 << 8),
};
// typedefs
public:
typedef ut::LinkList<Voice, 0xec> LinkList;
+3
View File
@@ -18,6 +18,9 @@ namespace nw4r { namespace snd { namespace detail
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2ffb36
class VoiceManager
{
public:
static const int VOICE_MAX = AX_VOICE_MAX;
static const int WORK_SIZE_MAX = VOICE_MAX * sizeof(Voice);
// methods
public:
// instance accessors
+21
View File
@@ -17,6 +17,27 @@ extern "C" {
#define AX_SAMPLES_PER_FRAME_RMT 18
#define AX_FRAME_SIZE (AX_SAMPLES_PER_FRAME * AX_SAMPLE_DEPTH_BYTES)
/**
* Stereo: Left, Right, Surround
* DPL2: Left, Right, Left Surround, Right Surround
*/
typedef enum {
AX_STEREO_L,
AX_STEREO_R,
AX_STEREO_S,
AX_STEREO_MAX
} AXStereoChannel;
typedef enum {
AX_DPL2_L,
AX_DPL2_R,
AX_DPL2_LS,
AX_DPL2_RS,
AX_DPL2_MAX
} AXDPL2Channel;
typedef void (*AXAuxCallback)(void *chans, void *context);
void __AXAuxInit(void);
+4 -4
View File
@@ -32,8 +32,8 @@ enum WPADResult_et {
WPAD_ERR_OK = 0,
WPAD_ERR_NO_CONTROLLER = -1, /* name known from asserts */
WPAD_ERR_COMMUNICATION_ERROR = -2, // [RT3P54] has this as WPAD_ERR_BUSY
WPAD_ERR_3 = -3, // [RT3P54] has this as WPAD_ERR_TRANSFER
WPAD_ERR_BUSY = -2, // [RT3P54] has this as WPAD_ERR_BUSY
WPAD_ERR_TRANSFER = -3, // [RT3P54] has this as WPAD_ERR_TRANSFER
WPAD_ERR_INVALID = -4, /* name comes from [R89JEL] */
// WPAD_ERR_5 = -5, /* unknown */
// WPAD_ERR_6 = -6, /* unknown */
@@ -260,8 +260,8 @@ enum WPADMotorCommand_et {
// WPADControlSpeaker
typedef u32 WPADSpeakerCommand;
enum WPADSpeakerCommand_et {
WPAD_SPEAKER_DISABLE = 0,
WPAD_SPEAKER_ENABLE = 1, // might be ON? see HBMRemoteSpk.cpp
WPAD_SPEAKER_OFF = 0,
WPAD_SPEAKER_ON = 1, // might be ON? see HBMRemoteSpk.cpp
WPAD_SPEAKER_MUTE = 2,
WPAD_SPEAKER_UNMUTE = 3,
WPAD_SPEAKER_PLAY = 4, // figured out from HBM usage
@@ -8,6 +8,9 @@ inline size_t strlen(const char *str) {
return ::strlen(str);
}
using ::strncpy;
using ::strncat;
inline char *strcpy(char *dest, const char *src) {
return ::strcpy(dest, src);
}
+148
View File
@@ -306,6 +306,14 @@ OutputMode AxManager::GetOutputMode()
return mOutputMode;
}
void AxManager::SetMasterVolume(f32 volume, int frame) {
mMasterVolume.SetTarget(ut::Clamp(volume, 0.0f, 1.0f), (frame + 2) / 3);
if (frame == 0) {
VoiceManager::GetInstance().UpdateAllVoicesSync(Voice::SYNC_AX_VE);
}
}
void AxManager::SetMainOutVolume(f32 volume, int frames)
{
volume = ut::Clamp(volume, 0.0f, 1.0f);
@@ -326,6 +334,73 @@ void AxManager::AxCallbackFunc()
(*GetInstance().mNextAxRegisterCallback)();
}
bool AxManager::AppendEffect(AuxBus bus, FxBase* pFx) {
if (!mAuxFadeVolume[bus].IsFinished()) {
ShutdownEffect(bus);
}
mAuxFadeVolume[bus].SetTarget(1.0f, 0);
switch (bus) {
case AUX_A: {
AXSetAuxAReturnVolume(AX_MAX_VOLUME);
break;
}
case AUX_B: {
AXSetAuxBReturnVolume(AX_MAX_VOLUME);
break;
}
case AUX_C: {
AXSetAuxCReturnVolume(AX_MAX_VOLUME);
break;
}
}
if (!pFx->StartUp()) {
return false;
}
ut::AutoInterruptLock lock;
if (GetEffectList(bus).IsEmpty()) {
switch (bus) {
case AUX_A: {
AXRegisterAuxACallback(AuxCallbackFunc,
reinterpret_cast<void*>(bus));
break;
}
case AUX_B: {
AXRegisterAuxBCallback(AuxCallbackFunc,
reinterpret_cast<void*>(bus));
break;
}
case AUX_C: {
AXRegisterAuxCCallback(AuxCallbackFunc,
reinterpret_cast<void*>(bus));
break;
}
}
mAuxCallbackWaitCounter[bus] = 2;
}
GetEffectList(bus).PushBack(pFx);
return true;
}
void AxManager::ClearEffect(AuxBus bus, int frame) {
if (frame == 0) {
ShutdownEffect(bus);
return;
}
mAuxFadeVolume[bus].SetTarget(0.0f, (frame + 2) / 3);
}
void AxManager::ShutdownEffect(AuxBus bus)
{
ut::AutoInterruptLock lock;
@@ -365,4 +440,77 @@ void AxManager::SetBiquadFilterCallback(int type,
sBiquadFilterCallbackTable[type] = biquad;
}
void AxManager::AuxCallbackFunc(void* pChans, void* pContext) {
int num;
void* buffer[AX_DPL2_MAX];
void** ppChans = static_cast<void**>(pChans);
AuxBus bus = static_cast<AuxBus>(reinterpret_cast<u32>(pContext));
if (GetInstance().GetOutputMode() == OUTPUT_MODE_DPL2) {
num = AX_DPL2_MAX;
buffer[AX_DPL2_L] = ppChans[AX_DPL2_L];
buffer[AX_DPL2_R] = ppChans[AX_DPL2_R];
buffer[AX_DPL2_LS] = ppChans[AX_DPL2_LS];
buffer[AX_DPL2_RS] = ppChans[AX_DPL2_RS];
} else {
num = AX_STEREO_MAX;
buffer[AX_STEREO_L] = ppChans[AX_STEREO_L];
buffer[AX_STEREO_R] = ppChans[AX_STEREO_R];
buffer[AX_STEREO_S] = ppChans[AX_STEREO_S];
}
if (GetInstance().mAuxCallbackWaitCounter[bus] > 0) {
GetInstance().mAuxCallbackWaitCounter[bus]--;
for (int i = 0; i < num; i++) {
std::memset(buffer[i], 0, FX_BUFFER_SIZE);
}
} else if (GetInstance().GetEffectList(bus).IsEmpty()) {
for (int i = 0; i < num; i++) {
std::memset(buffer[i], 0, FX_BUFFER_SIZE);
}
} else {
for (FxBase::LinkList::Iterator it =
GetInstance().GetEffectList(bus).GetBeginIter();
it != GetInstance().GetEffectList(bus).GetEndIter(); ++it) {
it->UpdateBuffer(num, buffer, FX_BUFFER_SIZE, FX_SAMPLE_FORMAT,
FX_SAMPLE_RATE, GetInstance().GetOutputMode());
}
}
}
void AxManager::PrepareReset() {
if (mOldAidCallback != NULL) {
return;
}
mVolumeForReset.SetTarget(0.0f, 3);
mResetReadyCounter = -1;
mOldAidCallback = AIRegisterDMACallback(AiDmaCallbackFunc);
}
void AxManager::AiDmaCallbackFunc() {
static bool finishedFlag = false;
AxManager& r = GetInstance();
r.mOldAidCallback();
if (finishedFlag) {
if (r.mResetReadyCounter < 0) {
AXSetMaxDspCycles(0);
r.mResetReadyCounter = AUX_CALLBACK_WAIT_FRAME;
}
} else if (r.mVolumeForReset.GetValue() == 0.0f) {
finishedFlag = true;
}
if (r.mResetReadyCounter > 0) {
r.mResetReadyCounter--;
}
}
}}} // namespace nw4r::snd::detail
+56
View File
@@ -1 +1,57 @@
#include "nw4r/snd/snd_AxfxImpl.h"
#include "nw4r/ut/ut_algorithm.h"
namespace nw4r {
namespace snd {
namespace detail {
AxfxImpl* AxfxImpl::mCurrentFx = NULL;
u32 AxfxImpl::mAllocatedSize = 0;
bool AxfxImpl::CreateHeap(void* pBuffer, u32 size) {
mHeap = MEMCreateFrmHeap(pBuffer, size);
return mHeap != NULL;
}
void AxfxImpl::DestroyHeap() {
if (mHeap != NULL) {
MEMDestroyFrmHeap(mHeap);
}
}
void AxfxImpl::HookAlloc(AXFXAllocHook* pAllocHook, AXFXFreeHook* pFreeHook) {
AXFXGetHooks(pAllocHook, pFreeHook);
AXFXSetHooks(Alloc, Free);
mCurrentFx = this;
}
void AxfxImpl::RestoreAlloc(AXFXAllocHook allocHook, AXFXFreeHook freeHook) {
AXFXSetHooks(allocHook, freeHook);
mCurrentFx = NULL;
}
void* AxfxImpl::Alloc(u32 size) {
void* pBlock = MEMAllocFromFrmHeap(mCurrentFx->mHeap, size);
mCurrentFx->mAllocCount++;
mAllocatedSize += ut::RoundUp(size, 4);
return pBlock;
}
void AxfxImpl::Free(void* pBlock) {
#pragma unused(pBlock)
if (mCurrentFx->mAllocCount != 0) {
mCurrentFx->mAllocCount--;
}
if (mCurrentFx->mAllocCount == 0) {
MEMFreeToFrmHeap(mCurrentFx->mHeap, MEM_FRM_HEAP_FREE_ALL);
}
}
} // namespace detail
} // namespace snd
} // namespace nw4r
+231 -2
View File
@@ -1,6 +1,235 @@
/* Only implemented to the extent necessary to match data sections. */
#include "nw4r/snd/snd_DvdSoundArchive.h"
#include "nw4r/ut/ut_DvdLockedFileStream.h"
#include <cstring>
#include <new>
nw4r::snd::DvdSoundArchive::DvdSoundArchive() {}
nw4r::snd::DvdSoundArchive::DvdFileStream::DvdFileStream() {}
namespace nw4r {
namespace snd {
class DvdSoundArchive::DvdFileStream : public ut::DvdLockedFileStream {
public:
DvdFileStream(const DVDFileInfo* pFileInfo, u32 offset, u32 size);
DvdFileStream(s32 entrynum, u32 offset, u32 size);
virtual s32 Read(void* pDst, u32 size); // at 0x14
virtual void Seek(s32 offset, u32 origin); // at 0x44
virtual u32 Tell() const {
return ut::DvdFileStream::Tell() - mOffset;
} // at 0x58
virtual u32 GetSize() const {
return mSize;
} // at 0x40
private:
s32 mOffset; // at 0x70
s32 mSize; // at 0x74
};
DvdSoundArchive::DvdSoundArchive() : mOpen(false) {}
DvdSoundArchive::~DvdSoundArchive() {
Close();
}
bool DvdSoundArchive::Open(s32 entrynum) {
if (!DVDFastOpen(entrynum, &mFileInfo)) {
return false;
}
mOpen = true;
return LoadFileHeader();
}
bool DvdSoundArchive::Open(const char* pPath) {
s32 entrynum = DVDConvertPathToEntrynum(pPath);
if (entrynum < 0) {
return false;
}
if (!Open(entrynum)) {
return false;
}
char extRoot[FILE_PATH_MAX];
for (int i = std::strlen(pPath) - 1; i >= 0; i--) {
if (pPath[i] == '/' || pPath[i] == '\\') {
// @bug Long path can overflow extRoot buffer
std::strncpy(extRoot, pPath, i);
extRoot[i] = '\0';
SetExternalFileRoot(extRoot);
break;
}
}
return true;
}
void DvdSoundArchive::Close() {
DVDClose(&mFileInfo);
mOpen = false;
Shutdown();
}
ut::FileStream* DvdSoundArchive::OpenStream(void* pBuffer, int size, u32 offset,
u32 length) const {
if (!mOpen) {
return NULL;
}
if (size < sizeof(DvdFileStream)) {
return NULL;
}
return new (pBuffer) DvdFileStream(&mFileInfo, offset, length);
}
ut::FileStream* DvdSoundArchive::OpenExtStream(void* pBuffer, int size,
const char* pExtPath, u32 offset,
u32 length) const {
if (!mOpen) {
return NULL;
}
if (size < sizeof(DvdFileStream)) {
return NULL;
}
s32 entrynum = DVDConvertPathToEntrynum(pExtPath);
if (entrynum < 0) {
return NULL;
}
return new (pBuffer) DvdFileStream(entrynum, offset, length);
}
int DvdSoundArchive::detail_GetRequiredStreamBufferSize() const {
return sizeof(DvdFileStream);
}
bool DvdSoundArchive::LoadFileHeader() {
u8 headerArea[detail::SoundArchiveFile::HEADER_AREA_SIZE];
static const u32 headerAlignSize =
ut::RoundUp(sizeof(detail::SoundArchiveFile::Header), 32);
void* pFile = ut::RoundUp<u8>(headerArea, 32);
s32 bytesRead =
DVDReadPrio(&mFileInfo, pFile, headerAlignSize, 0, DVD_PRIO_MEDIUM);
if (bytesRead != headerAlignSize) {
return false;
}
mFileReader.Init(pFile);
Setup(&mFileReader);
return true;
}
bool DvdSoundArchive::LoadHeader(void* pBuffer, u32 size) {
u32 infoSize = mFileReader.GetInfoChunkSize();
s32 infoOffset = mFileReader.GetInfoChunkOffset();
if (size < infoSize) {
return false;
}
s32 bytesRead =
DVDReadPrio(&mFileInfo, pBuffer, infoSize, infoOffset, DVD_PRIO_MEDIUM);
if (bytesRead != infoSize) {
return false;
}
mFileReader.SetInfoChunk(pBuffer, infoSize);
return true;
}
bool DvdSoundArchive::LoadLabelStringData(void* pBuffer, u32 size) {
u32 labelSize = mFileReader.GetLabelStringChunkSize();
s32 labelOffset = mFileReader.GetLabelStringChunkOffset();
if (size < labelSize) {
return false;
}
s32 bytesRead = DVDReadPrio(&mFileInfo, pBuffer, labelSize, labelOffset,
DVD_PRIO_MEDIUM);
if (bytesRead != labelSize) {
return false;
}
mFileReader.SetStringChunk(pBuffer, labelSize);
return true;
}
DvdSoundArchive::DvdFileStream::DvdFileStream(const DVDFileInfo* pFileInfo,
u32 offset, u32 size)
: DvdLockedFileStream(pFileInfo, false), mOffset(offset), mSize(size) {
if (mSize == 0) {
mSize = ut::DvdFileStream::GetSize();
}
ut::DvdFileStream::Seek(mOffset, SEEKORG_BEG);
}
DvdSoundArchive::DvdFileStream::DvdFileStream(s32 entrynum, u32 offset,
u32 size)
: DvdLockedFileStream(entrynum), mOffset(offset), mSize(size) {
if (mSize == 0) {
mSize = ut::DvdFileStream::GetSize();
}
ut::DvdFileStream::Seek(mOffset, SEEKORG_BEG);
}
s32 DvdSoundArchive::DvdFileStream::Read(void* pDst, u32 size) {
u32 endOffset = mOffset + mSize;
u32 startOffset = ut::DvdFileStream::Tell();
if (startOffset + size > endOffset) {
size = ut::RoundUp(endOffset - ut::DvdFileStream::Tell(), 32);
}
return DvdLockedFileStream::Read(pDst, size);
}
void DvdSoundArchive::DvdFileStream::Seek(s32 offset, u32 origin) {
switch (origin) {
case SEEKORG_BEG: {
offset += mOffset;
break;
}
case SEEKORG_CUR: {
offset += ut::DvdFileStream::Tell();
break;
}
case SEEKORG_END: {
offset = mOffset + mSize - offset;
break;
}
default: {
return;
}
}
if (offset < mOffset) {
offset = mOffset;
} else if (offset > mOffset + mSize) {
offset = mOffset + mSize;
}
ut::DvdFileStream::Seek(offset, SEEKORG_BEG);
}
}}
+20
View File
@@ -16,6 +16,7 @@
#include "nw4r/snd/snd_SoundThread.h"
#include "nw4r/NW4RAssert.hpp"
#include "nw4r/snd/snd_global.h"
/*******************************************************************************
* types
@@ -30,6 +31,17 @@ namespace nw4r { namespace ut { struct LinkListNode; }}
namespace nw4r { namespace snd { namespace detail {
ExternalSoundPlayer::ExternalSoundPlayer() : mPlayableCount(1) {}
ExternalSoundPlayer::~ExternalSoundPlayer() {
NW4R_RANGE_FOR_NO_AUTO_INC(it, mSoundList)
{
decltype(it) curItr = it++;
curItr->DetachExternalSoundPlayer(this);
}
}
// not sure which one uses this exactly, maybe StopAllSound?
DECOMP_FORCE_CLASS_METHOD(
BasicSound::ExtSoundPlayerPlayLinkList,
@@ -64,6 +76,14 @@ bool ExternalSoundPlayer::AppendSound(BasicSound *sound)
return true;
}
void ExternalSoundPlayer::SetPlayableSoundCount(int count) {
mPlayableCount = count;
while (GetPlayingSoundCount() > GetPlayableSoundCount()) {
GetLowestPrioritySound()->Shutdown();
}
}
void ExternalSoundPlayer::RemoveSound(BasicSound *sound)
{
mSoundList.Erase(sound);
+135
View File
@@ -1 +1,136 @@
#include "nw4r/snd/snd_FrameHeap.h"
#include <new>
namespace nw4r {
namespace snd {
namespace detail {
FrameHeap::FrameHeap() : mHandle(NULL) {}
FrameHeap::~FrameHeap() {
if (IsValid()) {
Destroy();
}
}
bool FrameHeap::Create(void* pBase, u32 size) {
if (IsValid()) {
Destroy();
}
void* pEnd = static_cast<u8*>(pBase) + size;
pBase = ut::RoundUp(pBase, 4);
if (pBase > pEnd) {
return false;
}
mHandle = MEMCreateFrmHeap(pBase, ut::GetOffsetFromPtr(pBase, pEnd));
if (mHandle == NULL) {
return false;
}
if (!NewSection()) {
return false;
}
return true;
}
void FrameHeap::Destroy() {
if (!IsValid()) {
return;
}
ClearSection();
MEMFreeToFrmHeap(mHandle, MEM_FRM_HEAP_FREE_ALL);
MEMDestroyFrmHeap(mHandle);
mHandle = NULL;
}
void FrameHeap::Clear() {
ClearSection();
MEMFreeToFrmHeap(mHandle, MEM_FRM_HEAP_FREE_ALL);
NewSection();
}
void* FrameHeap::Alloc(u32 size, FreeCallback pCallback, void* pCallbackArg) {
void* pBuffer = MEMAllocFromFrmHeapEx(
mHandle, BLOCK_BUFFER_SIZE + ut::RoundUp(size, HEAP_ALIGN), HEAP_ALIGN);
if (pBuffer == NULL) {
return NULL;
}
Block* pBlock = new (pBuffer) Block(size, pCallback, pCallbackArg);
mSectionList.GetBack().AppendBlock(pBlock);
return pBlock->GetBufferAddr();
}
int FrameHeap::SaveState() {
if (!MEMRecordStateForFrmHeap(mHandle, mSectionList.GetSize())) {
return -1;
}
if (!NewSection()) {
MEMFreeByStateToFrmHeap(mHandle, 0);
return -1;
}
return GetCurrentLevel();
}
void FrameHeap::LoadState(int id) {
if (id == 0) {
Clear();
return;
}
while (id < static_cast<int>(mSectionList.GetSize())) {
Section& rSection = mSectionList.GetBack();
rSection.~Section();
mSectionList.Erase(&rSection);
}
MEMFreeByStateToFrmHeap(mHandle, id);
MEMRecordStateForFrmHeap(mHandle, mSectionList.GetSize());
NewSection();
}
int FrameHeap::GetCurrentLevel() const {
return mSectionList.GetSize() - 1;
}
u32 FrameHeap::GetFreeSize() const {
u32 freeSize = MEMGetAllocatableSizeForFrmHeapEx(mHandle, HEAP_ALIGN);
if (freeSize < BLOCK_BUFFER_SIZE) {
return 0;
}
return ut::RoundDown(freeSize - BLOCK_BUFFER_SIZE, HEAP_ALIGN);
}
bool FrameHeap::NewSection() {
void* pSection = MEMAllocFromFrmHeap(mHandle, sizeof(Section));
if (pSection == NULL) {
return false;
}
mSectionList.PushBack(new (pSection) Section());
return true;
}
void FrameHeap::ClearSection() {
while (!mSectionList.IsEmpty()) {
Section& rSection = mSectionList.GetBack();
rSection.~Section();
mSectionList.Erase(&rSection);
}
}
} // namespace detail
} // namespace snd
} // namespace nw4r
+263
View File
@@ -1 +1,264 @@
#include "nw4r/snd/snd_NandSoundArchive.h"
#include <cstring>
#include <new>
namespace nw4r {
namespace snd {
class NandSoundArchive::NandFileStream : public ut::NandFileStream {
public:
NandFileStream(const NANDFileInfo* pFileInfo, u32 offset, u32 size);
NandFileStream(const char* pPath, u32 offset, u32 size);
virtual s32 Read(void* pDst, u32 size); // at 0x14
virtual void Seek(s32 offset, u32 origin); // at 0x44
virtual u32 Tell() const {
return ut::NandFileStream::Tell() - mOffset;
} // at 0x58
virtual u32 GetSize() const {
return mSize;
} // at 0x40
private:
s32 mOffset; // at 0x16C
s32 mSize; // at 0x170
};
NandSoundArchive::NandSoundArchive() : mOpen(false) {}
NandSoundArchive::~NandSoundArchive() {
Close();
}
bool NandSoundArchive::Open(const char* pPath) {
if (mOpen) {
Close();
}
if (NANDOpen(pPath, &mFileInfo, NAND_ACCESS_READ)) {
return false;
}
mOpen = true;
if (!LoadFileHeader()) {
return false;
}
char currentDir[64];
NANDGetCurrentDir(currentDir);
u32 currDirLen = std::strlen(currentDir);
char extRoot[FILE_PATH_MAX];
std::strncpy(extRoot, currentDir, currDirLen + 1);
for (int i = std::strlen(pPath) - 1; i >= 0; i--) {
if (pPath[i] == '/' || pPath[i] == '\\') {
// @bug Long path can overflow extRoot buffer
std::strncat(extRoot, pPath, i);
extRoot[currDirLen + i] = '\0';
break;
}
}
SetExternalFileRoot(extRoot);
return true;
}
void NandSoundArchive::Close() {
if (mOpen) {
NANDClose(&mFileInfo);
mOpen = false;
}
Shutdown();
}
ut::FileStream* NandSoundArchive::OpenStream(void* pBuffer, int size,
u32 offset, u32 length) const {
if (!mOpen) {
return NULL;
}
if (size < sizeof(NandFileStream)) {
return NULL;
}
return new (pBuffer) NandFileStream(&mFileInfo, offset, length);
}
ut::FileStream* NandSoundArchive::OpenExtStream(void* pBuffer, int size,
const char* pExtPath,
u32 offset, u32 length) const {
if (!mOpen) {
return NULL;
}
if (size < sizeof(NandFileStream)) {
return NULL;
}
NandFileStream* pExtStream =
new (pBuffer) NandFileStream(pExtPath, offset, length);
if (!pExtStream->IsAvailable()) {
pExtStream->~NandFileStream();
return NULL;
}
return pExtStream;
}
int NandSoundArchive::detail_GetRequiredStreamBufferSize() const {
return sizeof(NandFileStream);
}
bool NandSoundArchive::LoadFileHeader() {
u8 headerArea[detail::SoundArchiveFile::HEADER_AREA_SIZE];
static const u32 headerAlignSize =
ut::RoundUp(sizeof(detail::SoundArchiveFile::Header), 32);
void* pFile = ut::RoundUp<u8>(headerArea, 32);
if (NANDSeek(&mFileInfo, 0, NAND_SEEK_BEG) != NAND_RESULT_OK) {
return false;
}
s32 bytesRead = NANDRead(&mFileInfo, pFile, headerAlignSize);
if (bytesRead != headerAlignSize) {
return false;
}
mFileReader.Init(pFile);
Setup(&mFileReader);
return true;
}
bool NandSoundArchive::LoadHeader(void* pBuffer, u32 size) {
u32 infoSize = mFileReader.GetInfoChunkSize();
u32 infoOffsetU = mFileReader.GetInfoChunkOffset();
s32 infoOffset = *reinterpret_cast<s32*>(&infoOffsetU);
if (size < infoSize) {
return false;
}
s32 currOffset = NANDSeek(&mFileInfo, infoOffset, NAND_SEEK_BEG);
if (currOffset != infoOffset) {
return false;
}
s32 bytesRead = NANDRead(&mFileInfo, pBuffer, infoSize);
if (bytesRead != infoSize) {
return false;
}
mFileReader.SetInfoChunk(pBuffer, infoSize);
return true;
}
bool NandSoundArchive::LoadLabelStringData(void* pBuffer, u32 size) {
u32 labelSize = mFileReader.GetLabelStringChunkSize();
u32 labelOffsetU = mFileReader.GetLabelStringChunkOffset();
s32 labelOffset = *reinterpret_cast<s32*>(&labelOffsetU);
if (size < labelSize) {
return false;
}
s32 currOffset = NANDSeek(&mFileInfo, labelOffset, NAND_SEEK_BEG);
if (currOffset != labelOffset) {
return false;
}
s32 bytesRead = NANDRead(&mFileInfo, pBuffer, labelSize);
if (bytesRead != labelSize) {
return false;
}
mFileReader.SetStringChunk(pBuffer, labelSize);
return true;
}
NandSoundArchive::NandFileStream::NandFileStream(const NANDFileInfo* pFileInfo,
u32 offset, u32 size)
: ut::NandFileStream(pFileInfo, NAND_ACCESS_READ, false),
mOffset(offset),
mSize(size) {
if (IsAvailable()) {
if (mSize == 0) {
mSize = ut::NandFileStream::GetSize();
}
ut::NandFileStream::Seek(mOffset, SEEKORG_BEG);
}
}
NandSoundArchive::NandFileStream::NandFileStream(const char* pPath, u32 offset,
u32 size)
: ut::NandFileStream(pPath, NAND_ACCESS_READ),
mOffset(offset),
mSize(size) {
if (IsAvailable()) {
if (mSize == 0) {
mSize = ut::NandFileStream::GetSize();
}
ut::NandFileStream::Seek(mOffset, SEEKORG_BEG);
}
}
s32 NandSoundArchive::NandFileStream::Read(void* pDst, u32 size) {
u32 endOffset = mOffset + mSize;
u32 startOffset = ut::NandFileStream::Tell();
if (startOffset + size > endOffset) {
size = ut::RoundUp(endOffset - ut::NandFileStream::Tell(), 32);
}
s32 bytesRead = ut::NandFileStream::Read(pDst, size);
DCStoreRange(pDst, size);
return bytesRead;
}
void NandSoundArchive::NandFileStream::Seek(s32 offset, u32 origin) {
switch (origin) {
case SEEKORG_BEG: {
offset += mOffset;
break;
}
case SEEKORG_CUR: {
offset += ut::NandFileStream::Tell();
break;
}
case SEEKORG_END: {
offset = mOffset + mSize - offset;
break;
}
default: {
return;
}
}
if (offset < mOffset) {
offset = mOffset;
} else if (offset > mOffset + mSize) {
offset = mOffset + mSize;
}
ut::NandFileStream::Seek(offset, SEEKORG_BEG);
}
}}
+378
View File
@@ -1 +1,379 @@
#include "nw4r/snd/snd_RemoteSpeaker.h"
#include "common.h"
#include "nw4r/snd/snd_RemoteSpeakerManager.h"
#include "nw4r/ut/ut_Lock.h"
#include <cstring>
namespace nw4r {
namespace snd {
RemoteSpeaker::RemoteSpeaker()
: mInitFlag(false),
mPlayFlag(false),
mEnableFlag(false),
mFirstEncodeFlag(false),
mValidCallbackFlag(false),
mCommandBusyFlag(false),
// mForceResumeFlag(false),
mState(STATE_INVALID),
mUserCommand(COMMAND_NONE),
mInternalCommand(COMMAND_NONE),
mWpadCallback(nullptr) {
OSCreateAlarm(&mContinueAlarm);
OSSetAlarmUserData(&mContinueAlarm, this);
OSCreateAlarm(&mIntervalAlarm);
OSSetAlarmUserData(&mIntervalAlarm, this);
}
void RemoteSpeaker::InitParam() {
ClearParam();
// mForceResumeFlag = false;
mContinueFlag = false;
mPlayFlag = false;
mEnableFlag = true;
mIntervalFlag = false;
}
void RemoteSpeaker::ClearParam() {
mPlayFlag = false;
mEnableFlag = false;
OSCancelAlarm(&mContinueAlarm);
mContinueFlag = false;
OSCancelAlarm(&mIntervalAlarm);
mIntervalFlag = false;
}
bool RemoteSpeaker::Setup(WPADCallback pCallback) {
ut::AutoInterruptLock lock;
InitParam();
if (mWpadCallback != NULL) {
mWpadCallback(mChannelIndex, WPAD_ERR_OK);
mValidCallbackFlag = false;
}
mWpadCallback = pCallback;
mUserCommand = COMMAND_SPEAKER_ON;
mInitFlag = true;
return true;
}
void RemoteSpeaker::Shutdown(WPADCallback pCallback) {
ut::AutoInterruptLock lock;
ClearParam();
if (mWpadCallback != NULL) {
mWpadCallback(mChannelIndex, WPAD_ERR_OK);
mValidCallbackFlag = false;
}
mUserCommand = COMMAND_SPEAKER_OFF;
mWpadCallback = pCallback;
mInitFlag = false;
}
bool RemoteSpeaker::EnableOutput(bool enable) {
if (!mInitFlag) {
return false;
}
mEnableFlag = enable;
return true;
}
bool RemoteSpeaker::IsEnabledOutput() const {
if (!mInitFlag) {
return false;
}
return mEnableFlag;
}
void RemoteSpeaker::Update() {
if (mCommandBusyFlag) {
return;
}
SpeakerCommand command =
mUserCommand != COMMAND_NONE ? mUserCommand : mInternalCommand;
mUserCommand = COMMAND_NONE;
mInternalCommand = COMMAND_NONE;
ExecCommand(command);
}
void RemoteSpeaker::ExecCommand(SpeakerCommand command) {
switch (command) {
case COMMAND_NONE: {
break;
}
case COMMAND_SPEAKER_ON: {
mValidCallbackFlag = true;
mCommandBusyFlag = true;
mState = STATE_EXEC_SPEAKER_ON;
WPADControlSpeaker(mChannelIndex, WPAD_SPEAKER_ON, SpeakerOnCallback);
break;
}
case COMMAND_SPEAKER_PLAY: {
mValidCallbackFlag = true;
mCommandBusyFlag = true;
mState = STATE_EXEC_SPEAKER_PLAY;
WPADControlSpeaker(mChannelIndex, WPAD_SPEAKER_PLAY,
SpeakerPlayCallback);
break;
}
case COMMAND_SPEAKER_OFF: {
mValidCallbackFlag = true;
mCommandBusyFlag = true;
mState = STATE_EXEC_SPEAKER_OFF;
WPADControlSpeaker(mChannelIndex, WPAD_SPEAKER_OFF, SpeakerOffCallback);
break;
}
}
}
void RemoteSpeaker::UpdateStreamData(const s16* pRmtSamples) {
if (!IsAvailable()) {
return;
}
bool playFlag = true;
bool silentFlag = mEnableFlag ? IsAllSampleZero(pRmtSamples) : true;
if (silentFlag /*|| mForceResumeFlag*/) {
playFlag = false;
}
bool firstFlag = !mPlayFlag && playFlag;
bool lastFlag = mPlayFlag && !playFlag;
if (playFlag) {
ut::AutoInterruptLock lock;
if (!WPADCanSendStreamData(mChannelIndex)) {
return;
}
u32 wencMode = !mFirstEncodeFlag ? WENC_FLAG_USER_INFO : 0;
mFirstEncodeFlag = false;
u8 adpcmBuffer[SAMPLES_PER_ENCODED_PACKET];
WENCGetEncodeData(&mEncodeInfo, wencMode, pRmtSamples,
SAMPLES_PER_AUDIO_PACKET, adpcmBuffer);
s32 result = WPADSendStreamData(mChannelIndex, adpcmBuffer,
SAMPLES_PER_ENCODED_PACKET);
if (result != WPAD_ERR_OK) {
mInternalCommand = COMMAND_SPEAKER_ON;
mState = STATE_INVALID;
InitParam();
return;
}
}
if (firstFlag) {
ut::AutoInterruptLock lock;
if (!mContinueFlag) {
OSSetAlarm(&mContinueAlarm,
OS_SEC_TO_TICKS(CONTINUOUS_PLAY_INTERVAL_MINUTES * 60LL),
ContinueAlarmHandler);
mContinueBeginTime = OSGetTime();
mContinueFlag = true;
}
OSCancelAlarm(&mIntervalAlarm);
mIntervalFlag = false;
}
if (lastFlag) {
ut::AutoInterruptLock lock;
mIntervalFlag = true;
OSCancelAlarm(&mIntervalAlarm);
OSSetAlarm(&mIntervalAlarm, OS_SEC_TO_TICKS(1LL), IntervalAlarmHandler);
}
mPlayFlag = playFlag;
}
bool RemoteSpeaker::IsAllSampleZero(const s16* pSample) {
const u32* pBuffer = reinterpret_cast<const u32*>(pSample);
bool zeroFlag = true;
for (int i = 0; i < SAMPLES_PER_ENCODED_PACKET; i++) {
if (pBuffer[i] != 0) {
zeroFlag = false;
break;
}
}
return zeroFlag;
}
void RemoteSpeaker::SpeakerOnCallback(s32 chan, s32 result) {
RemoteSpeaker& r =
detail::RemoteSpeakerManager::GetInstance().GetRemoteSpeaker(chan);
switch (result) {
case WPAD_ERR_OK: {
r.mFirstEncodeFlag = true;
std::memset(&r.mEncodeInfo, 0, sizeof(WENCInfo));
r.mState = STATE_SPEAKER_ON;
r.mInternalCommand = COMMAND_SPEAKER_PLAY;
break;
}
case WPAD_ERR_BUSY: {
r.mInternalCommand = COMMAND_SPEAKER_ON;
break;
}
case WPAD_ERR_TRANSFER: {
r.mState = STATE_INVALID;
break;
}
case WPAD_ERR_NO_CONTROLLER: {
r.mState = STATE_INVALID;
break;
}
default: {
r.mState = STATE_INVALID;
break;
}
}
if (result != WPAD_ERR_OK && result != WPAD_ERR_BUSY) {
r.NotifyCallback(chan, result);
}
r.mCommandBusyFlag = false;
}
void RemoteSpeaker::SpeakerPlayCallback(s32 chan, s32 result) {
RemoteSpeaker& r =
detail::RemoteSpeakerManager::GetInstance().GetRemoteSpeaker(chan);
switch (result) {
case WPAD_ERR_OK: {
r.mState = STATE_SPEAKER_PLAY;
break;
}
case WPAD_ERR_BUSY: {
r.mInternalCommand = COMMAND_SPEAKER_PLAY;
break;
}
case WPAD_ERR_TRANSFER: {
r.mState = STATE_INVALID;
break;
}
case WPAD_ERR_NO_CONTROLLER: {
r.mState = STATE_INVALID;
break;
}
default: {
r.mState = STATE_INVALID;
break;
}
}
if (result != WPAD_ERR_BUSY) {
r.NotifyCallback(chan, result);
}
r.mCommandBusyFlag = false;
}
void RemoteSpeaker::SpeakerOffCallback(s32 chan, s32 result) {
RemoteSpeaker& r =
detail::RemoteSpeakerManager::GetInstance().GetRemoteSpeaker(chan);
switch (result) {
case WPAD_ERR_OK: {
r.mState = STATE_SPEAKER_OFF;
break;
}
case WPAD_ERR_BUSY: {
r.mInternalCommand = COMMAND_SPEAKER_OFF;
break;
}
case WPAD_ERR_TRANSFER: {
r.mState = STATE_INVALID;
break;
}
case WPAD_ERR_NO_CONTROLLER: {
r.mState = STATE_INVALID;
break;
}
default: {
r.mState = STATE_INVALID;
break;
}
}
if (result != WPAD_ERR_BUSY) {
r.NotifyCallback(chan, result);
}
r.mCommandBusyFlag = false;
}
void RemoteSpeaker::NotifyCallback(s32 chan, s32 result) {
if (mValidCallbackFlag && mWpadCallback != NULL) {
mWpadCallback(chan, result);
mWpadCallback = NULL;
}
}
void RemoteSpeaker::ContinueAlarmHandler(OSAlarm* pAlarm, OSContext* pCtx) {
#pragma unused(pCtx)
ut::AutoInterruptLock lock;
RemoteSpeaker* p = static_cast<RemoteSpeaker*>(OSGetAlarmUserData(pAlarm));
// p->mForceResumeFlag = true;
p->mContinueFlag = false;
}
void RemoteSpeaker::IntervalAlarmHandler(OSAlarm* pAlarm, OSContext* pCtx) {
#pragma unused(pCtx)
ut::AutoInterruptLock lock;
RemoteSpeaker* p = static_cast<RemoteSpeaker*>(OSGetAlarmUserData(pAlarm));
if (p->mIntervalFlag) {
OSCancelAlarm(&p->mContinueAlarm);
// p->mForceResumeFlag = false;
p->mContinueFlag = false;
}
p->mIntervalFlag = false;
}
} // namespace snd
} // namespace nw4r
+74
View File
@@ -1 +1,75 @@
#include "nw4r/snd/snd_RemoteSpeakerManager.h"
#include "rvl/AX/AXOut.h"
namespace nw4r {
namespace snd {
namespace detail {
RemoteSpeakerManager& RemoteSpeakerManager::GetInstance() {
static RemoteSpeakerManager instance;
return instance;
}
RemoteSpeakerManager::RemoteSpeakerManager() : mInitialized(false) {
for (int i = 0; i < WPAD_MAX_CONTROLLERS; i++) {
mSpeaker[i].SetChannelIndex(i);
}
}
RemoteSpeaker& RemoteSpeakerManager::GetRemoteSpeaker(int idx) {
return mSpeaker[idx];
}
void RemoteSpeakerManager::Setup() {
if (mInitialized) {
return;
}
OSCreateAlarm(&mRemoteSpeakerAlarm);
OSSetPeriodicAlarm(&mRemoteSpeakerAlarm, OSGetTime(),
OS_NSEC_TO_TICKS(SPEAKER_ALARM_PERIOD_NSEC),
RemoteSpeakerAlarmProc);
mInitialized = true;
}
void RemoteSpeakerManager::Shutdown() {
if (!mInitialized) {
return;
}
OSCancelAlarm(&mRemoteSpeakerAlarm);
mInitialized = false;
}
void RemoteSpeakerManager::RemoteSpeakerAlarmProc(OSAlarm* pAlarm,
OSContext* pCtx) {
#pragma unused(pAlarm)
#pragma unused(pCtx)
RemoteSpeakerManager& r = GetInstance();
s16 samples[RemoteSpeaker::SAMPLES_PER_AUDIO_PACKET];
if (AXRmtGetSamplesLeft() < RemoteSpeaker::SAMPLES_PER_AUDIO_PACKET) {
return;
}
for (int i = 0; i < WPAD_MAX_CONTROLLERS; i++) {
if (r.mSpeaker[i].IsAvailable()) {
AXRmtGetSamples(i, samples,
RemoteSpeaker::SAMPLES_PER_AUDIO_PACKET);
r.mSpeaker[i].UpdateStreamData(samples);
}
r.mSpeaker[i].Update();
}
AXRmtAdvancePtr(RemoteSpeaker::SAMPLES_PER_AUDIO_PACKET);
}
} // namespace detail
} // namespace snd
} // namespace nw4r
+4
View File
@@ -241,6 +241,10 @@ void SeqPlayer::Skip(OffsetType offsetType, int offset)
// SeqPlayer::SetTempoRatio ([R89JEL]:/bin/RVL/Debug/mainD.MAP:13781)
DECOMP_FORCE(NW4RAssert_String(tempoRatio >= 0.0f));
void SeqPlayer::SetTempoRatio(f32 tempo) {
mTempoRatio = tempo;
}
void SeqPlayer::SetChannelPriority(int priority)
{
// specifically not the source variant
+4
View File
@@ -169,6 +169,10 @@ void SeqSound::Shutdown()
// SeqSound::SetTempoRatio ([R89JEL]:/bin/RVL/Debug/mainD.MAP:13849)
DECOMP_FORCE(NW4RAssert_String(tempoRatio >= 0.0f));
void SeqSound::SetTempoRatio(f32 tempo) {
mSeqPlayer.SetTempoRatio(tempo);
}
void SeqSound::SetChannelPriority(int priority)
{
// specifically not the source variant
+293
View File
@@ -1 +1,294 @@
#include "nw4r/snd/snd_Sound3DManager.h"
#include "nw4r/snd/snd_AxManager.h"
#include "nw4r/snd/snd_Sound3DListener.h"
#include "nw4r/snd/snd_SoundHandle.h"
#include "nw4r/math.h"
#include <cmath>
namespace nw4r {
namespace snd {
namespace {
/**
* Solves the linear equation:
* a*x + b*y + c = d
*
* Where:
* a = dFactor - cFactor
* b = dAngle - cAngle
* c = cAngle * cFactor
* d = dAngle * dFactor
*/
inline f32 SolveLinerFunction(f32 x, f32 dAngle, f32 cAngle, f32 dFactor,
f32 cFactor) { // @typo
if (dAngle == cAngle) {
return (dFactor + cFactor) / 2;
}
f32 b = dAngle - cAngle;
return x * (cFactor - dFactor) / b +
(dAngle * dFactor - cAngle * cFactor) / b;
}
} // namespace
Sound3DManager::Sound3DManager()
: mMaxPriorityReduction(32),
mSpeakerAngleStereo(NW4R_MATH_PI / 4),
mFrontSpeakerAngleDpl2(NW4R_MATH_PI / 6),
mRearSpeakerAngleDpl2(2 * NW4R_MATH_PI / 3),
mInitPan(0.0f),
mPanRange(0.9f) {}
u32 Sound3DManager::GetRequiredMemSize(const SoundArchive* pArchive) {
u32 numParam = 0;
SoundArchive::SoundArchivePlayerInfo playerInfo;
if (pArchive->ReadSoundArchivePlayerInfo(&playerInfo)) {
numParam += playerInfo.seqSoundCount;
numParam += playerInfo.strmSoundCount;
numParam += playerInfo.waveSoundCount;
}
return numParam * sizeof(Sound3DActorParam);
}
bool Sound3DManager::Setup(const SoundArchive* pArchive, void* pBuffer,
u32 size) {
#pragma unused(pArchive)
mParamPool.Create(pBuffer, size);
return true;
}
void Sound3DManager::detail_Update(SoundParam* pParam, u32 id,
detail::BasicSound* pSound, const void* pArg,
u32 flags) {
SoundHandle handle;
if (pSound != NULL) {
handle.detail_AttachSoundAsTempHandle(pSound);
}
Update(pParam, id, pSound != NULL ? &handle : NULL, pArg, flags);
}
void Sound3DManager::Update(SoundParam* pParam, u32 id, SoundHandle* pHandle,
const void* pArg, u32 flags) {
#pragma unused(id)
#pragma unused(pHandle)
f32 angle;
f32 panLR, panFR;
f32 pan, surroundPan;
const Sound3DActorParam* pActorParam =
static_cast<const Sound3DActorParam*>(pArg);
Sound3DListener* pListener = GetListener();
if (pListener == NULL) {
pParam->volume = 0.0f;
return;
}
math::VEC3 relativePos;
VEC3Transform(&relativePos, &pListener->GetMatrix(),
&pActorParam->position);
f32 distance = VEC3Len(&relativePos);
f32 volume = 1.0f;
if ((flags & (PARAM_UPDATE_VOLUME | PARAM_UPDATE_PRIORITY)) &&
distance > pListener->GetMaxVolumeDistance()) {
switch (pActorParam->soundParam.decayCurve) {
case DECAY_CURVE_LOGARITHMIC: {
f32 units = (distance - pListener->GetMaxVolumeDistance()) /
pListener->GetUnitDistance();
volume =
std::pow(pActorParam->soundParam.decayRatio / 256.0f, units);
break;
}
case DECAY_CURVE_LINEAR: {
f32 units = (distance - pListener->GetMaxVolumeDistance()) /
pListener->GetUnitDistance() *
pActorParam->soundParam.decayRatio;
units = units / 256.0f;
volume = ut::Max(0.0f, 1.0f - units);
break;
}
}
}
if ((flags & PARAM_UPDATE_VOLUME) &&
!(pActorParam->soundParam.flags & PARAM_UPDATE_VOLUME)) {
pParam->volume = volume;
}
if (flags & (PARAM_UPDATE_PAN | PARAM_UPDATE_SURROUND_PAN)) {
math::VEC3 adjustedPos;
if (0.0f == distance) {
adjustedPos.z = 0.0f;
adjustedPos.y = 0.0f;
adjustedPos.x = 0.0f;
} else {
math::VEC3 relativeXZ(relativePos.x, 0.0f, relativePos.z);
f32 distanceXZ = VEC3Len(&relativeXZ);
if (distanceXZ > pListener->GetInteriorSize()) {
relativeXZ.x *= pListener->GetInteriorSize() / distanceXZ;
relativeXZ.z *= pListener->GetInteriorSize() / distanceXZ;
}
f32 ratioXZ = VEC3Len(&relativeXZ);
adjustedPos.x = relativePos.x * ratioXZ / distance;
adjustedPos.y = 0.0f;
adjustedPos.z = relativePos.z * ratioXZ / distance;
}
angle = atan2(adjustedPos.x, -adjustedPos.z);
f32 distanceNrm = VEC3Len(&adjustedPos) / pListener->GetInteriorSize();
switch (detail::AxManager::GetInstance().GetOutputMode()) {
case OUTPUT_MODE_SURROUND:
case OUTPUT_MODE_DPL2: {
static f32 angleRearLeft = -mRearSpeakerAngleDpl2;
static f32 angleFrontLeft = -mFrontSpeakerAngleDpl2;
static f32 angleFrontRight = mFrontSpeakerAngleDpl2;
static f32 angleRearRight = mRearSpeakerAngleDpl2;
// clang-format off
if (angle < angleRearLeft) {
panLR = SolveLinerFunction(angle, -NW4R_MATH_PI, angleRearLeft, -1.0f, 0.0f);
panFR = 1.0f;
} else if (angle < -NW4R_MATH_PI / 2) {
panLR = -1.0f;
panFR = SolveLinerFunction(angle, angleRearLeft, -NW4R_MATH_PI / 2, 0.0f, 1.0f);
} else if (angle < angleFrontLeft) {
panLR = -1.0f;
panFR = SolveLinerFunction(angle, -NW4R_MATH_PI / 2, angleFrontLeft, -1.0f, 0.0f);
} else if (angle < angleFrontRight) {
panLR = SolveLinerFunction(angle, angleFrontLeft, angleFrontRight, 1.0f, -1.0f);
panFR = -1.0f;
} else if (angle < NW4R_MATH_PI / 2) {
panLR = 1.0f;
panFR = SolveLinerFunction(angle, angleFrontRight, NW4R_MATH_PI / 2, 0.0f, -1.0f);
} else if (angle < angleRearRight) {
panLR = 1.0f;
panFR = SolveLinerFunction(angle, NW4R_MATH_PI / 2, angleRearRight, 1.0f, 0.0f);
} else {
panLR = SolveLinerFunction(angle, angleRearRight, NW4R_MATH_PI, 0.0f, 1.0f);
panFR = 1.0f;
}
// clang-format on
f32 cosAvg = (std::cosf(mFrontSpeakerAngleDpl2) +
std::cosf(mRearSpeakerAngleDpl2)) /
2.0f;
f32 rearFactor =
cosAvg / (cosAvg + -std::cosf(mRearSpeakerAngleDpl2));
panLR *= mPanRange;
panFR *= mPanRange;
pan = panLR * distanceNrm;
surroundPan =
mInitPan + (1.0f + (panFR * distanceNrm +
rearFactor * (1.0f - distanceNrm)));
break;
}
case OUTPUT_MODE_STEREO: {
static f32 angleRearLeft = -NW4R_MATH_PI + mSpeakerAngleStereo;
static f32 angleFrontLeft = -mSpeakerAngleStereo;
static f32 angleFrontRight = mSpeakerAngleStereo;
static f32 angleRearRight = NW4R_MATH_PI - mSpeakerAngleStereo;
// clang-format off
if (angle < angleRearLeft) {
panLR = SolveLinerFunction(angle, -NW4R_MATH_PI, angleRearLeft, -1.0f, 0.0f);
panFR = 1.0f;
} else if (angle < angleFrontLeft) {
panLR = -1.0f;
panFR = SolveLinerFunction(angle, angleRearLeft, angleFrontLeft, -1.0f, 1.0f);
} else if (angle < angleFrontRight) {
panLR = SolveLinerFunction(angle, angleFrontLeft, angleFrontRight, 1.0f, -1.0f);
panFR = -1.0f;
} else if (angle < angleRearRight) {
panLR = 1.0f;
panFR = SolveLinerFunction(angle, angleFrontRight, angleRearRight, 1.0f, -1.0f);
} else {
panLR = SolveLinerFunction(angle, angleRearRight, NW4R_MATH_PI, 0.0f, 1.0f);
panFR = 1.0f;
}
// clang-format on
panLR *= mPanRange;
panFR *= mPanRange;
surroundPan = 1.0f + panFR * distanceNrm;
pan = panLR * distanceNrm;
break;
}
case OUTPUT_MODE_MONO:
default: {
pan = 0.0f;
surroundPan = 0.0f;
break;
}
}
}
if ((flags & PARAM_UPDATE_PAN) &&
!(pActorParam->soundParam.flags & PARAM_UPDATE_PAN)) {
pParam->pan = pan;
}
if ((flags & PARAM_UPDATE_SURROUND_PAN) &&
!(pActorParam->soundParam.flags & PARAM_UPDATE_SURROUND_PAN)) {
pParam->surroundPan = surroundPan;
}
if ((flags & PARAM_UPDATE_PRIORITY) &&
!(pActorParam->soundParam.flags & PARAM_UPDATE_PRIORITY)) {
pParam->priority =
-static_cast<int>((1.0f - volume) * GetMaxPriorityReduction());
}
}
void* Sound3DManager::detail_AllocAmbientArg(u32 size) {
if (size != sizeof(Sound3DActorParam)) {
return NULL;
}
return mParamPool.Alloc();
}
void Sound3DManager::detail_FreeAmbientArg(void* pArg,
const detail::BasicSound* pSound) {
#pragma unused(pSound)
mParamPool.Free(static_cast<Sound3DActorParam*>(pArg));
}
Sound3DManager::Sound3DActorParam::Sound3DActorParam() : userParam(-1) {
soundParam.flags = 0;
soundParam.decayCurve = DECAY_CURVE_LOGARITHMIC;
soundParam.decayRatio = 128;
}
} // namespace snd
} // namespace nw4r
+64
View File
@@ -72,11 +72,27 @@ u32 SoundArchive::GetGroupCount() const
return mFileReader->GetGroupCount();
}
const char* SoundArchive::GetSoundLabelString(u32 id) const {
return mFileReader->GetSoundLabelString(id);
}
u32 SoundArchive::ConvertLabelStringToSoundId(char const *label) const
{
return mFileReader->ConvertLabelStringToSoundId(label);
}
u32 SoundArchive::ConvertLabelStringToPlayerId(const char* pLabel) const {
return mFileReader->ConvertLabelStringToPlayerId(pLabel);
}
u32 SoundArchive::ConvertLabelStringToGroupId(const char* pLabel) const {
return mFileReader->ConvertLabelStringToGroupId(pLabel);
}
u32 SoundArchive::GetSoundUserParam(u32 id) const {
return mFileReader->GetSoundUserParam(id);
}
SoundArchive::SoundType SoundArchive::GetSoundType(u32 soundId) const
{
return mFileReader->GetSoundType(soundId);
@@ -226,4 +242,52 @@ ut::FileStream *SoundArchive::OpenExtStreamImpl(void *buffer, int size,
return OpenExtStream(buffer, size, fullPath, begin, length);
}
ut::FileStream* SoundArchive::detail_OpenGroupStream(u32 id, void* pBuffer,
int bufferSize) const {
GroupInfo groupInfo;
if (!detail_ReadGroupInfo(id, &groupInfo)) {
return NULL;
}
if (groupInfo.extFilePath != NULL) {
return OpenExtStreamImpl(pBuffer, bufferSize, groupInfo.extFilePath,
groupInfo.offset, groupInfo.size);
}
return OpenStream(pBuffer, bufferSize, groupInfo.offset, groupInfo.size);
}
ut::FileStream*
SoundArchive::detail_OpenGroupWaveDataStream(u32 id, void* pBuffer,
int bufferSize) const {
GroupInfo groupInfo;
if (!detail_ReadGroupInfo(id, &groupInfo)) {
return NULL;
}
if (groupInfo.extFilePath != NULL) {
return OpenExtStreamImpl(pBuffer, bufferSize, groupInfo.extFilePath,
groupInfo.waveDataOffset,
groupInfo.waveDataSize);
}
return OpenStream(pBuffer, bufferSize, groupInfo.waveDataOffset,
groupInfo.waveDataSize);
}
void SoundArchive::SetExternalFileRoot(const char* pExtFileRoot) {
u32 len = std::strlen(pExtFileRoot);
u32 nullPos = len;
if (pExtFileRoot[len - 1] != '/') {
mExtFileRoot[len] = '/';
nullPos++;
}
mExtFileRoot[nullPos] = '\0';
// @bug Long path can overflow mExtFileRoot buffer
std::strncpy(mExtFileRoot, pExtFileRoot, len);
}
}} // namespace nw4r::snd
+138
View File
@@ -1 +1,139 @@
#include "nw4r/snd/snd_SoundArchiveLoader.h"
#include "nw4r/snd/snd_SoundArchive.h"
#include "nw4r/snd/snd_SoundMemoryAllocatable.h"
namespace nw4r {
namespace snd {
namespace detail {
SoundArchiveLoader::SoundArchiveLoader(const SoundArchive& rArchive)
: mArc(rArchive), mStream(NULL) {
OSInitMutex(&mMutex);
}
SoundArchiveLoader::~SoundArchiveLoader() {}
void* SoundArchiveLoader::LoadGroup(u32 id,
SoundMemoryAllocatable* pAllocatable,
void** ppWaveBuffer, u32 blockSize) {
ut::detail::AutoLock<OSMutex> lock(mMutex);
FileStreamHandle groupHandle(
mArc.detail_OpenGroupStream(id, mStreamArea, sizeof(mStreamArea)));
if (!groupHandle) {
return NULL;
}
if (!groupHandle->CanSeek() || !groupHandle->CanRead()) {
return NULL;
}
void* pGroupBuffer = pAllocatable->Alloc(groupHandle->GetSize());
if (pGroupBuffer == NULL) {
return NULL;
}
mStream = groupHandle.GetFileStream();
if (blockSize == 0) {
s32 bytesRead = groupHandle->Read(pGroupBuffer, groupHandle->GetSize());
if (bytesRead < 0) {
mStream = NULL;
return NULL;
}
} else {
u8* pReadPtr = static_cast<u8*>(pGroupBuffer);
u32 bytesLeft = groupHandle->GetSize();
while (bytesLeft) {
s32 bytesRead =
groupHandle->Read(pReadPtr, ut::Min(blockSize, bytesLeft));
if (bytesRead < 0) {
mStream = NULL;
return NULL;
}
if (bytesLeft > bytesRead) {
bytesLeft -= bytesRead;
pReadPtr += bytesRead;
} else {
bytesLeft = 0;
}
}
}
mStream = NULL;
SoundArchive::GroupInfo groupInfo;
if (!mArc.detail_ReadGroupInfo(id, &groupInfo)) {
return NULL;
}
if (groupInfo.waveDataSize != 0) {
FileStreamHandle waveHandle(mArc.detail_OpenGroupWaveDataStream(
id, mStreamArea, sizeof(mStreamArea)));
if (!waveHandle) {
return NULL;
}
if (!waveHandle->CanSeek() || !waveHandle->CanRead()) {
return NULL;
}
void* pWaveBuffer = pAllocatable->Alloc(waveHandle->GetSize());
if (pWaveBuffer == NULL) {
return NULL;
}
mStream = waveHandle.GetFileStream();
if (blockSize == 0) {
s32 bytesRead =
waveHandle->Read(pWaveBuffer, waveHandle->GetSize());
if (bytesRead < 0) {
mStream = NULL;
return NULL;
}
} else {
u8* pReadPtr = static_cast<u8*>(pWaveBuffer);
u32 bytesLeft = waveHandle->GetSize();
while (bytesLeft) {
s32 bytesRead =
waveHandle->Read(pReadPtr, ut::Min(blockSize, bytesLeft));
if (bytesRead < 0) {
mStream = NULL;
return NULL;
}
if (bytesLeft > bytesRead) {
bytesLeft -= bytesRead;
pReadPtr += bytesRead;
} else {
bytesLeft = 0;
}
}
}
mStream = NULL;
if (ppWaveBuffer != NULL) {
*ppWaveBuffer = pWaveBuffer;
}
} else if (ppWaveBuffer != NULL) {
*ppWaveBuffer = NULL;
}
return pGroupBuffer;
}
} // namespace detail
} // namespace snd
} // namespace nw4r
+46
View File
@@ -16,6 +16,7 @@
#include "nw4r/snd/snd_Bank.h"
#include "nw4r/snd/snd_BasicSound.h"
#include "nw4r/snd/snd_SoundArchiveLoader.h"
#include "nw4r/snd/snd_debug.h"
#include "nw4r/snd/snd_DisposeCallbackManager.h"
#include "nw4r/snd/snd_ExternalSoundPlayer.h"
@@ -1327,6 +1328,51 @@ void SoundArchivePlayer::UpdateCommonSoundParam(
*/
DECOMP_FORCE(NW4RAssertAligned_String(loadBlockSize, 32));
bool SoundArchivePlayer::LoadGroup(u32 id, SoundMemoryAllocatable* pAllocatable,
u32 blockSize) {
if (!IsAvailable()) {
return false;
}
if (id >= mSoundArchive->GetGroupCount()) {
return false;
}
if (GetGroupAddress(id) != NULL) {
return true;
}
if (pAllocatable == NULL) {
return false;
}
detail::SoundArchiveLoader loader(*mSoundArchive);
void* pWaveBuffer;
const void* pGroup =
loader.LoadGroup(id, pAllocatable, &pWaveBuffer, blockSize);
if (pGroup == NULL) {
return NULL;
}
SetGroupAddress(id, pGroup);
SetGroupWaveDataAddress(id, pWaveBuffer);
return true;
}
bool SoundArchivePlayer::LoadGroup(const char* pLabel,
SoundMemoryAllocatable* pAllocatable,
u32 blockSize) {
u32 id = mSoundArchive->ConvertLabelStringToGroupId(pLabel);
if (id == SoundArchive::INVALID_ID) {
return false;
}
return LoadGroup(id, pAllocatable, blockSize);
}
void SoundArchivePlayer::InvalidateData(void const *start, void const *end)
{
if (mFileTable)
+14
View File
@@ -21,6 +21,20 @@
namespace nw4r { namespace snd {
void SoundHandle::detail_AttachSoundAsTempHandle(detail::BasicSound* pSound) {
mSound = pSound;
if (pSound->IsAttachedTempGeneralHandle()) {
mSound->DetachTempGeneralHandle();
}
if (mSound->IsAttachedTempSpecialHandle()) {
mSound->DetachTempSpecialHandle();
}
mSound->mTempGeneralHandle = this;
}
void SoundHandle::detail_AttachSound(detail::BasicSound *sound)
{
NW4RAssertPointerNonnull_Line(81, sound);
+64
View File
@@ -1 +1,65 @@
#include "nw4r/snd/snd_SoundHeap.h"
#include "nw4r/snd/snd_DisposeCallbackManager.h"
#include "nw4r/snd/snd_SoundThread.h"
namespace nw4r {
namespace snd {
SoundHeap::SoundHeap() {
OSInitMutex(&mMutex);
}
SoundHeap::~SoundHeap() {
mFrameHeap.Destroy();
}
bool SoundHeap::Create(void* pBase, u32 size) {
return mFrameHeap.Create(pBase, size);
}
void SoundHeap::Destroy() {
mFrameHeap.Destroy();
}
void* SoundHeap::Alloc(u32 size) {
ut::detail::AutoLock<OSMutex> lock(mMutex);
return mFrameHeap.Alloc(size, DisposeCallbackFunc, NULL);
}
void* SoundHeap::Alloc(u32 size, detail::FrameHeap::FreeCallback pCallback,
void* pCallbackArg) {
ut::detail::AutoLock<OSMutex> lock(mMutex);
return mFrameHeap.Alloc(size, pCallback, pCallbackArg);
}
void SoundHeap::Clear() {
ut::detail::AutoLock<OSMutex> lockHeap(mMutex);
detail::SoundThread::AutoLock lockThread;
mFrameHeap.Clear();
}
int SoundHeap::SaveState() {
ut::detail::AutoLock<OSMutex> lock(mMutex);
return mFrameHeap.SaveState();
}
void SoundHeap::LoadState(int id) {
ut::detail::AutoLock<OSMutex> lockHeap(mMutex);
detail::SoundThread::AutoLock lockThread;
mFrameHeap.LoadState(id);
}
void SoundHeap::DisposeCallbackFunc(void* pBuffer, u32 size,
void* pCallbackArg) {
detail::DisposeCallbackManager::GetInstance().Dispose(pBuffer, size,
pCallbackArg);
detail::DisposeCallbackManager::GetInstance().DisposeWave(pBuffer, size,
pCallbackArg);
}
} // namespace snd
} // namespace nw4r
+35
View File
@@ -78,6 +78,27 @@ namespace nw4r { namespace snd
namespace nw4r { namespace snd {
void SoundSystem::InitSoundSystem(s32 soundThreadPriority,
s32 dvdThreadPriority) {
const int defaultWorkSize = DEFAULT_SOUND_THREAD_STACK_SIZE +
DEFAULT_DVD_THREAD_STACK_SIZE +
detail::AxVoiceManager::WORK_SIZE_MAX +
detail::VoiceManager::WORK_SIZE_MAX +
detail::ChannelManager::WORK_SIZE_MAX;
static u8 defaultSoundSystemWork[defaultWorkSize] ALIGN_DECL(32);
// OSRegisterVersion(NW4R_SND_Version_);
SoundSystemParam param;
param.soundThreadPriority = soundThreadPriority;
param.dvdThreadPriority = dvdThreadPriority;
// @bug This function ignores the specified buffer size
InitSoundSystem(param, defaultSoundSystemWork,
sizeof(defaultSoundSystemWork));
}
u32 SoundSystem::GetRequiredMemSize(SoundSystemParam const &param)
{
// could have just used align assert? idk
@@ -210,6 +231,20 @@ bool SoundSystem::IsInitializedSoundSystem()
return sInitialized;
}
void SoundSystem::WaitForResetReady() {
if (!sInitialized) {
return;
}
u32 start = OSGetTick();
while (!detail::AxManager::GetInstance().IsResetReady()) {
if (OS_TICKS_TO_SEC(OSGetTick() - start) > 0) {
break;
}
}
}
// SoundSystem::WaitForResetReady ([R89JEL]:/bin/RVL/Debug/mainD.MAP:14493)
DECOMP_FORCE("SoundSystem::WaitForResetReady is TIME OUT.\n");