Files
ss/include/nw4r/snd/snd_Channel.h
T
2025-05-26 01:49:31 +02:00

286 lines
9.5 KiB
C++

#ifndef NW4R_SND_CHANNEL_H
#define NW4R_SND_CHANNEL_H
/*******************************************************************************
* headers
*/
#include <climits> // USHRT_MAX
#include "common.h"
#include "nw4r/snd/snd_EnvGenerator.h"
#include "nw4r/snd/snd_InstancePool.h"
#include "nw4r/snd/snd_global.h"
#include "nw4r/snd/snd_Lfo.h"
#include "nw4r/snd/snd_MoveValue.h"
#include "nw4r/snd/snd_Voice.h"
#include "nw4r/ut/ut_LinkList.h"
#include "nw4r/NW4RAssert.hpp"
/*******************************************************************************
* types
*/
// forward declarations
namespace nw4r { namespace snd { namespace detail { class WaveDataLocationCallback; }}}
namespace nw4r { namespace snd { namespace detail { struct WaveInfo; }}}
/*******************************************************************************
* classes and functions
*/
namespace nw4r { namespace snd { namespace detail
{
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2c353
// NOTE: different from ketteiban: no remote fields
class Channel
{
// enums
public:
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x290ad
enum ChannelCallbackStatus
{
CALLBACK_STATUS_STOPPED,
CALLBACK_STATUS_DROP,
CALLBACK_STATUS_FINISH,
CALLBACK_STATUS_CANCEL,
};
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2c2f1
enum LfoTarget
{
LFO_TARGET_PITCH,
LFO_TARGET_VOLUME,
LFO_TARGET_PAN,
};
// typedefs
public:
typedef void Callback(Channel *dropChannel,
ChannelCallbackStatus status,
u32 userData);
typedef ut::LinkList<Channel, 0xd8> LinkList;
// methods
public:
// instance managers
static Channel *AllocChannel(int voiceChannelCount, int voiceOutCount,
int priority, Callback *callback,
u32 callbackData);
static void FreeChannel(Channel *channel);
// methods
void InitParam(Callback *callback, u32 callbackData);
void Start(WaveInfo const &waveParam, int length, u32 startOffset);
void Pause(bool flag)
{
mPauseFlag = flag;
mVoice->Pause(flag);
}
void Stop();
bool IsRelease() const
{
return mEnvelope.GetStatus() == EnvGenerator::STATUS_RELEASE;
}
bool IsPause() const { return mPauseFlag != false; }
bool IsActive() const { return mActiveFlag; }
bool IsAutoUpdateSweep() const { return mAutoSweep; }
f32 GetSweepValue() const;
s32 GetLength() const { return mLength; }
int GetAlternateAssignId() const { return mAlternateAssign; }
Voice *GetVoice() const { return mVoice; }
Channel *GetNextTrackChannel() const { return mNextLink; }
void SetDecay(int decay) { mEnvelope.SetDecay(decay); }
void SetRelease(int release) { mEnvelope.SetRelease(release); }
void SetAttack(int attack) { mEnvelope.SetAttack(attack); }
void SetSustain(int sustain) { mEnvelope.SetSustain(sustain); }
void SetHold(int hold) { mEnvelope.SetHold(hold); }
void SetLfoParam(LfoParam const &param) { mLfo.SetParam(param); }
void SetLfoTarget(LfoTarget type) { mLfoTarget = type; }
void SetReleasePriorityFix(bool fix) { mReleasePriorityFixFlag = fix; }
void SetReleaseIgnore(bool ignore) { mReleaseIgnoreFlag = ignore; }
void SetBiquadFilter(int type, f32 value);
void SetRemoteFilter(int filter) { mRemoteFilter = filter; }
void SetUserVolume(f32 volume) { mUserVolume = volume; }
void SetUserPitchRatio(f32 pitchRatio) { mUserPitchRatio = pitchRatio; }
void SetUserPan(f32 pan) { mUserPan = pan; }
void SetUserSurroundPan(f32 surroundPan)
{
mUserSurroundPan = surroundPan;
}
void SetRemoteOutVolume(int channel, f32 volume)
{
mRemoteOutVolume[channel] = volume;
}
void SetUserLpfFreq(f32 lpfFreq) { mUserLpfFreq = lpfFreq; }
void SetOutputLine(int lineFlag) { mOutputLineFlag = lineFlag; }
void SetMainOutVolume(f32 volume) { mMainOutVolume = volume; }
void SetMainSend(f32 send) { mMainSend = send; }
void SetFxSend(AuxBus bus, f32 send) { mFxSend[bus] = send; }
void SetUserPitch(f32 pitch) { mUserPitch = pitch; }
void SetSweepParam(f32 sweepPitch, int sweepTime, bool autoUpdate);
void SetInitVolume(f32 volume) { mInitVolume = volume; }
void SetInitPan(f32 pan) { mInitPan = pan; }
void SetInitSurroundPan(f32 surroundPan)
{
mInitSurroundPan = surroundPan;
}
void SetTune(f32 tune) { mTune = tune; }
void SetSilence(bool silenceFlag, int fadeTimes)
{
NW4RAssertHeaderClampedLRValue_Line(138, fadeTimes, 0, USHRT_MAX);
mSilenceVolume.SetTarget(silenceFlag ? SILENCE_VOLUME_MIN
: SILENCE_VOLUME_MAX,
fadeTimes);
}
void SetKey(int key) { mKey = key; }
void SetOriginalKey(int key) { mOriginalKey = key; }
void SetLength(s32 length) { mLength = length; }
void SetPanMode(PanMode panMode) { mPanMode = panMode; }
void SetPanCurve(PanCurve panCurve) { mPanCurve = panCurve; }
void SetAlternateAssignId(int id) { mAlternateAssign = id; }
void SetWaveDataLocationCallback(WaveDataLocationCallback *callback,
WaveInfo const *waveInfo)
{
mWaveDataLocationCallback = callback;
mWaveInfo = waveInfo;
}
void SetVoiceOutParam(int index, VoiceOutParam const &param)
{
mVoice->SetVoiceOutParam(index, param);
}
void SetNextTrackChannel(Channel *channel) { mNextLink = channel; }
void Update(bool doPeriodicProc);
void UpdateSweep(int count);
void Release();
void NoteOff();
private:
// cdtors
Channel();
~Channel();
// callbacks
static void VoiceCallbackFunc(Voice *voice,
Voice::VoiceCallbackStatus status,
void *arg);
// static members
public:
static u8 const SILENCE_VOLUME_MIN = 0;
static u8 const SILENCE_VOLUME_MAX = 255;
static int const ORIGINAL_KEY_INIT = 60;
static int const KEY_INIT = 60;
static int const PRIORITY_RELEASE = 1;
static int const CHANNEL_MAX = Voice::CHANNEL_MAX;
static int const CHANNEL_MIN = 1;
static int const CHANNEL_NUM;
// members
private:
EnvGenerator mEnvelope; // size 0x1c, offset 0x00
Lfo mLfo; // size 0x18, offset 0x1c
u8 mLfoTarget; // size 0x01, offset 0x34
bool mPauseFlag; // size 0x01, offset 0x35
bool mActiveFlag; // size 0x01, offset 0x36
bool mAllocFlag; // size 0x01, offset 0x37
bool mAutoSweep; // size 0x01, offset 0x38
bool mReleasePriorityFixFlag; // size 0x01, offset 0x39
u8 mReleaseIgnoreFlag; // size 0x01, offset 0x3a // not a bool?
u8 mBiquadType; // size 0x01, offset 0x3b
u8 mRemoteFilter; // size 0x01, offset 0x3c
/* 3 bytes padding */
f32 mUserVolume; // size 0x04, offset 0x40
f32 mUserPitchRatio; // size 0x04, offset 0x44
f32 mUserPan; // size 0x04, offset 0x48
f32 mUserSurroundPan; // size 0x04, offset 0x4c
f32 mUserLpfFreq; // size 0x04, offset 0x50
f32 mBiquadValue; // size 0x04, offset 0x54
int mOutputLineFlag; // size 0x04, offset 0x58
f32 mMainOutVolume; // size 0x04, offset 0x5c
f32 mMainSend; // size 0x04, offset 0x60
f32 mFxSend[AUX_BUS_NUM]; // size 0x0c, offset 0x64
f32 mRemoteOutVolume[4];
f32 mUserPitch; // size 0x04, offset 0x70
f32 mSweepPitch; // size 0x04, offset 0x74
s32 mSweepCounter; // size 0x04, offset 0x78
s32 mSweepLength; // size 0x04, offset 0x7c
f32 mInitVolume; // size 0x04, offset 0x80
f32 mInitPan; // size 0x04, offset 0x84
f32 mInitSurroundPan; // size 0x04, offset 0x88
f32 mTune; // size 0x04, offset 0x8c
MoveValue<u8, u16> mSilenceVolume; // size 0x06, offset 0x90
/* 2 bytes padding */
int mKey; // size 0x04, offset 0x98
int mOriginalKey; // size 0x04, offset 0x9c
s32 mLength; // size 0x04, offset 0xa0
PanMode mPanMode; // size 0x04, offset 0xa4
PanCurve mPanCurve; // size 0x04, offset 0xa8
int mAlternateAssign; // size 0x04, offset 0xac
Callback *mCallback; // size 0x04, offset 0xb0
u32 mCallbackData; // size 0x04, offset 0xb4
WaveDataLocationCallback *mWaveDataLocationCallback; // size 0x04, offset 0xb8
WaveInfo const *mWaveInfo; // size 0x04, offset 0xbc
Voice *mVoice; // size 0x04, offset 0xc0
Channel *mNextLink; // size 0x04, offset 0xc4
public:
ut::LinkListNode mLink; // size 0x08, offset 0xc8
// friends
private:
// for calling private constructor
template <class> friend class InstancePool;
}; // size 0xd0
// [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
static ChannelManager &GetInstance();
// methods
u32 GetRequiredMemSize(int channelCount);
void Setup(void *mem, u32 memSize);
void Shutdown();
Channel* Alloc();
void Free(Channel *channel);
void UpdateAllChannel();
private:
// cdtors
ChannelManager();
// members
private:
InstancePool<Channel> mPool; // size 0x04, offset 0x00
Channel::LinkList mChannelList; // size 0x0c, offset 0x04
bool mInitialized; // size 0x01, offset 0x10
/* 3 bytes padding */
u32 mChannelCount; // size 0x04, offset 0x14
void *mMem; // size 0x04, offset 0x18
u32 mMemSize; // size 0x04, offset 0x1c
}; // size 0x20
}}} // namespace nw4r::snd::detail
#endif // NW4R_SND_CHANNEL_H