mirror of
https://github.com/zeldaret/ss
synced 2026-08-12 20:02:26 -04:00
254 lines
7.7 KiB
C++
254 lines
7.7 KiB
C++
#ifndef NW4R_SND_SEQ_PLAYER_H
|
|
#define NW4R_SND_SEQ_PLAYER_H
|
|
|
|
/*******************************************************************************
|
|
* headers
|
|
*/
|
|
|
|
#include "common.h"
|
|
|
|
#include "nw4r/snd/snd_BasicPlayer.h"
|
|
#include "nw4r/snd/snd_DisposeCallbackManager.h" // DisposeCallback
|
|
#include "nw4r/snd/snd_SeqTrack.h"
|
|
#include "nw4r/snd/snd_SoundThread.h"
|
|
#include "nw4r/ut/ut_Lock.h"
|
|
|
|
/*******************************************************************************
|
|
* types
|
|
*/
|
|
|
|
// forward declarations
|
|
namespace nw4r { namespace snd { namespace detail { class Channel; }}}
|
|
namespace nw4r { namespace snd { namespace detail { class NoteOnCallback; }}}
|
|
namespace nw4r { namespace snd { namespace detail { struct NoteOnInfo; }}}
|
|
namespace nw4r { namespace snd { namespace detail { class SeqTrack; }}}
|
|
namespace nw4r { namespace snd { namespace detail { class SeqTrackAllocator; }}}
|
|
|
|
namespace nw4r { namespace snd
|
|
{
|
|
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2dbb2
|
|
struct SeqUserprocCallbackParam
|
|
{
|
|
s16 volatile *localVariable; // size 0x04, offset 0x00
|
|
s16 volatile *globalVariable; // size 0x04, offset 0x04
|
|
s16 volatile *trackVariable; // size 0x04, offset 0x08
|
|
bool cmpFlag; // size 0x01, offset 0x0C
|
|
/* 3 bytes padding */
|
|
}; // size 0x10
|
|
}} // namespace nw4r::snd
|
|
|
|
/*******************************************************************************
|
|
* classes
|
|
*/
|
|
|
|
namespace nw4r { namespace snd { namespace detail
|
|
{
|
|
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2dfad
|
|
class SeqPlayer : public BasicPlayer,
|
|
public DisposeCallback,
|
|
public SoundThread::PlayerCallback
|
|
{
|
|
// enums
|
|
public:
|
|
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2dee8
|
|
enum OffsetType
|
|
{
|
|
OFFSET_TYPE_TICK,
|
|
OFFSET_TYPE_MILLISEC,
|
|
};
|
|
|
|
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2df3b
|
|
enum SetupResult
|
|
{
|
|
SETUP_SUCCESS,
|
|
|
|
SETUP_ERR_CANNOT_ALLOCATE_TRACK,
|
|
|
|
SETUP_ERR_UNKNOWN
|
|
};
|
|
|
|
// nested types
|
|
public:
|
|
// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2cce4
|
|
struct ParserPlayerParam
|
|
{
|
|
u8 volume; // size 0x01, offset 0x00
|
|
u8 priority; // size 0x01, offset 0x01
|
|
u8 timebase; // size 0x01, offset 0x02
|
|
/* 1 byte padding */
|
|
u16 tempo; // size 0x02, offset 0x04
|
|
/* 2 bytes padding */
|
|
NoteOnCallback *callback; // size 0x04, offset 0x08
|
|
}; // size 0x0c
|
|
|
|
// typedefs
|
|
public:
|
|
typedef void SeqUserprocCallback(u16 procId,
|
|
SeqUserprocCallbackParam *param,
|
|
void *callbackData);
|
|
|
|
// methods
|
|
public:
|
|
// cdtors
|
|
SeqPlayer();
|
|
virtual ~SeqPlayer();
|
|
|
|
// virtual function ordering
|
|
// vtable BasicPlayer
|
|
virtual bool Start();
|
|
virtual void Stop();
|
|
virtual void Pause(bool flag);
|
|
virtual bool IsActive() const { return mActiveFlag; }
|
|
virtual bool IsStarted() const { return mStartedFlag; }
|
|
virtual bool IsPause() const { return mPauseFlag; }
|
|
|
|
// vtable DisposeCallback
|
|
virtual void InvalidateData(void const *start, void const *end);
|
|
virtual void InvalidateWaveData(void const *, void const *) {}
|
|
|
|
// vtable SeqPlayer
|
|
/* WARNING: must come before SoundThread::PlayerCallback virtual
|
|
* functions
|
|
*/
|
|
virtual void ChannelCallback(Channel *channel ATTR_UNUSED) {}
|
|
|
|
// vtable SoundThread::PlayerCallback
|
|
virtual void OnUpdateFrameSoundThread() { Update(); }
|
|
virtual void OnShutdownSoundThread() { Stop(); }
|
|
|
|
// methods
|
|
SetupResult Setup(SeqTrackAllocator *trackAllocator, u32 allocTracks,
|
|
int voiceOutCount, NoteOnCallback *callback);
|
|
void Update();
|
|
void Skip(OffsetType offsetType, int offset);
|
|
void Shutdown();
|
|
|
|
bool IsReleasePriorityFix() const { return mReleasePriorityFixFlag; }
|
|
f32 GetPanRange() const { return mPanRange; }
|
|
int GetVoiceOutCount() const { return mVoiceOutCount; }
|
|
ParserPlayerParam &GetParserPlayerParam() { return mParserParam; }
|
|
SeqTrack *GetPlayerTrack(int trackNo);
|
|
s16 volatile *GetVariablePtr(int varNo);
|
|
|
|
s16 GetLocalVariable(int varNo) const;
|
|
void SetLocalVariable(int varNo, s16 value);
|
|
static void SetGlobalVariable(int varNo, s16 value);
|
|
|
|
void SetTempoRatio(f32 tempo);
|
|
void SetReleasePriorityFix(bool fix);
|
|
void SetChannelPriority(int priority);
|
|
void SetSeqUserprocCallback(SeqUserprocCallback *callback, void *arg);
|
|
void SetPlayerTrack(int trackNo, SeqTrack *track);
|
|
|
|
f32 CalcTickPerMsec() const
|
|
{
|
|
return CalcTickPerMinute() / (60 * 1000);
|
|
}
|
|
f32 CalcTickPerMinute() const
|
|
{
|
|
return mParserParam.timebase * mParserParam.tempo * mTempoRatio;
|
|
}
|
|
|
|
u32 GetTickCounter() const {
|
|
return mTickCounter;
|
|
}
|
|
|
|
void SetSeqData(void const *seqBase, s32 seqOffset);
|
|
|
|
void CallSeqUserprocCallback(u16 procId, SeqTrack *track);
|
|
Channel *NoteOn(int bankNo, NoteOnInfo const ¬eOnInfo);
|
|
|
|
void SetTrackMute(u32 trackFlags, SeqMute mute);
|
|
void SetTrackSilence(u32 trackFlags, bool silence, int fadeFrames);
|
|
void SetTrackVolume(u32 trackFlags, f32 volume);
|
|
|
|
static void InitSeqPlayer();
|
|
|
|
private:
|
|
void InitParam(int voiceOutCount, NoteOnCallback *callback);
|
|
|
|
void UpdateChannelParam();
|
|
|
|
void CloseTrack(int trackNo);
|
|
void FinishPlayer();
|
|
|
|
int ParseNextTick(bool doNoteOn); // meant to be bool?
|
|
void UpdateTick(int msec);
|
|
void SkipTick();
|
|
|
|
template <typename T>
|
|
void SetTrackParam(u32 trackFlags, void (SeqTrack::*pSetter)(T), T param) {
|
|
ut::AutoInterruptLock lock;
|
|
|
|
for (int i = 0; i < TRACK_NUM && trackFlags != 0;
|
|
trackFlags >>= 1, i++) {
|
|
|
|
if (trackFlags & 1) {
|
|
SeqTrack* pTrack = GetPlayerTrack(i);
|
|
|
|
if (pTrack != NULL) {
|
|
(pTrack->*pSetter)(param);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
void SetTrackParam(u32 trackFlags, void (SeqTrack::*pSetter)(T, U), T param, U param2) {
|
|
ut::AutoInterruptLock lock;
|
|
|
|
for (int i = 0; i < TRACK_NUM && trackFlags != 0;
|
|
trackFlags >>= 1, i++) {
|
|
|
|
if (trackFlags & 1) {
|
|
SeqTrack* pTrack = GetPlayerTrack(i);
|
|
|
|
if (pTrack != NULL) {
|
|
(pTrack->*pSetter)(param, param2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// static members
|
|
public:
|
|
static int const MAX_SKIP_TICK_PER_FRAME = 768;
|
|
static int const DEFAULT_TEMPO = 120;
|
|
static int const DEFAULT_TIMEBASE = 48;
|
|
static int const VARIABLE_DEFAULT_VALUE = -1;
|
|
static int const TRACK_NUM_PER_PLAYER = 16;
|
|
static int const GLOBAL_VARIABLE_NUM = 16;
|
|
static int const PLAYER_VARIABLE_NUM = 16;
|
|
|
|
static const int TRACK_NUM = 16;
|
|
|
|
private:
|
|
static s16 mGlobalVariable[GLOBAL_VARIABLE_NUM];
|
|
|
|
// members
|
|
private:
|
|
/* base BasicPlayer */ // size 0x0a4, offset 0x000
|
|
/* base DisposeCallback */ // size 0x00c, offset 0x0a4
|
|
/* base SoundThread::PlayerCallback */ // size 0x00c, offset 0x0b0
|
|
bool mActiveFlag; // size 0x001, offset 0x0ec
|
|
bool mStartedFlag; // size 0x001, offset 0x0ed
|
|
bool mPauseFlag; // size 0x001, offset 0x0ee
|
|
bool mReleasePriorityFixFlag; // size 0x001, offset 0x0ef
|
|
f32 mPanRange; // size 0x004, offset 0x0f0
|
|
f32 mTempoRatio; // size 0x004, offset 0x0f4
|
|
f32 mTickFraction; // size 0x004, offset 0x0f8
|
|
u32 mSkipTickCounter; // size 0x004, offset 0x0fc
|
|
f32 mSkipTimeCounter; // size 0x004, offset 0x100
|
|
s32 mVoiceOutCount; // size 0x004, offset 0x104
|
|
ParserPlayerParam mParserParam; // size 0x00c, offset 0x108
|
|
SeqTrackAllocator *mSeqTrackAllocator; // size 0x004, offset 0x114
|
|
SeqUserprocCallback *mSeqUserprocCallback; // size 0x004, offset 0x118
|
|
void *mSeqUserprocCallbackArg; // size 0x004, offset 0x11c
|
|
SeqTrack *mTracks[TRACK_NUM_PER_PLAYER]; // size 0x040, offset 0x120
|
|
s16 volatile mLocalVariable[PLAYER_VARIABLE_NUM]; // size 0x020, offset 0x160
|
|
u32 mTickCounter; // size 0x004, offset 0x180
|
|
}; // size 0x184
|
|
}}} // namespace nw4r::snd::detail
|
|
|
|
#endif // NW4R_SND_SEQ_PLAYER_H
|