#ifndef D_SND_SOUND_H #define D_SND_SOUND_H #include "common.h" #include "d/snd/d_snd_types.h" #include "nw4r/snd/snd_SeqTrack.h" #include "nw4r/snd/snd_SoundHandle.h" #include "nw4r/snd/snd_SoundStartable.h" #include "nw4r/ut/ut_list.h" // Not sure, handles a bunch of floats, exists in a ton of variants class dSndControl_c { public: dSndControl_c(f32 value, f32 min, f32 max) : mResetValue(value), mMax(max), mMin(min), mCurrValue(value), mStartValue(value), mTargetValue(value), mDuration(0), mTimer(0), mIsLinked(false) {} ~dSndControl_c() {} virtual void configure(f32 value, f32 min, f32 max); // vt 0x08 virtual void reset(); // vt 0x0C virtual void set(f32 value, s32 frames); // vt 0x10 virtual void calc(); // vt 0x14 virtual void stop(); // vt 0x18 bool isLinked() const { return mIsLinked; } void setLinked(bool linked) { mIsLinked = linked; } f32 getCurrentValue() const { return mCurrValue; } f32 getTargetValue() const { return mTargetValue; } bool isFinished() const { return mTimer >= mDuration; } protected: /* 0x04 */ f32 mResetValue; /* 0x08 */ f32 mMax; /* 0x0C */ f32 mMin; /* 0x10 */ f32 mCurrValue; /* 0x14 */ f32 mStartValue; /* 0x18 */ f32 mTargetValue; /* 0x1C */ s32 mDuration; /* 0x20 */ s32 mTimer; /* 0x24 */ nw4r::ut::Node mNode; /* 0x2C */ bool mIsLinked; }; class dSndControlSound_c : public dSndControl_c { public: dSndControlSound_c(f32 value, f32 min, f32 max) : dSndControl_c(value, min, max) {} virtual void apply(dSndSound_c *pHandle) = 0; // vt 0x1C private: }; class dSndControlSoundVolume_c : public dSndControlSound_c { public: dSndControlSoundVolume_c() : dSndControlSound_c(1.0f, 0.0f, 2.0f) {} virtual void apply(dSndSound_c *pHandle) override; }; class dSndControlSoundPitch_c : public dSndControlSound_c { public: dSndControlSoundPitch_c() : dSndControlSound_c(1.0f, 0.25f, 4.0f) {} virtual void apply(dSndSound_c *pHandle) override; }; /** Stores pitch as a value from -24 to 24, exponentially scaling it to 0.25-4.0 */ class dSndControlSoundPitchLinear_c : public dSndControlSound_c { public: dSndControlSoundPitchLinear_c(); virtual void apply(dSndSound_c *pHandle) override; virtual void set(f32 value, s32 frames) override; void setControl(dSndControlSound_c *ctrl) { mpOtherControl = ctrl; } private: /* 0x30 */ dSndControlSound_c *mpOtherControl; }; class dSndControlSoundSeqTempoRatio_c : public dSndControlSound_c { public: dSndControlSoundSeqTempoRatio_c() : dSndControlSound_c(1.0f, 0.25f, 4.0f) {} virtual void apply(dSndSound_c *pHandle) override; }; class dSndControlSoundSeqTrackVolume_c : public dSndControlSound_c { public: dSndControlSoundSeqTrackVolume_c() : dSndControlSound_c(1.0f, 0.0f, 2.0f) {} virtual void apply(dSndSound_c *pHandle) override; void setMask(u16 mask) { mMask = mask; } private: /* 0x2E */ u16 mMask; }; class dSndControlSoundStrmTrackVolume_c : public dSndControlSound_c { public: dSndControlSoundStrmTrackVolume_c() : dSndControlSound_c(1.0f, 0.0f, 2.0f) {} virtual void apply(dSndSound_c *pHandle) override; void setMask(u16 mask) { mMask = mask; } private: /* 0x2E */ u16 mMask; }; class dSndSound_c : public nw4r::snd::SoundHandle { public: dSndSound_c(); ~dSndSound_c(); virtual void cancel(); // 0x08 virtual void calc(); // 0x0C virtual void fadeIn(u32 id, s32 fadeFrames); // 0x10 virtual nw4r::snd::SoundStartable::StartResult prepareSound(u32 soundId, u32 startOffset); // 0x14 virtual nw4r::snd::SoundStartable::StartResult prepareSound(const char *label, u32 startOffset); // 0x18 virtual void onPreparing(u32 soundId, u32 startOffset); // 0x1C virtual void stop(s32 fadeFrames); // 0x20 virtual void pause(bool pauseFlag, s32 fadeFrames); // 0x24 bool isStrmSound(); bool isWaveSound(); bool isSeqSound(); f32 getCurrentStrmTrackVolume(u32 index) const; void setVolume(f32 volume, s32 frames); void setPitchRelated(f32 pitch, s32 frames); void setLinearPitch(f32 pitch, s32 frames); void setTrackVolume(u16 trackFlags, f32 volume, s32 frames); void setStrmTrackVolume(u16 trackFlags, f32 volume, s32 frames); void setSingleSeqTrackVolume(u16 index, f32 volume, s32 frames); void setSingleStrmTrackVolume(u16 index, f32 volume, s32 frames); // why f32 frames? void setEachSeqTrackVolume(u16 trackFlags, f32 frames); void setEachStrmTrackVolume(u16 trackFlags, f32 frames); void setSeqTempoRatio(f32 ratio, s32 frames); void setSeqTrackMute(u16 trackFlags, nw4r::snd::SeqMute mute); void forceStop(); s32 readSeqTrackVariable(int varNo); void writeSeqTrackVariable(int varNo, s16 value); void linkCtrl(dSndControlSound_c *); void unlinkCtrl(dSndControlSound_c *); bool isPlaying() const { return mIsRunning && !mIsFadingOut && IsAttachedSound(); } bool isPlayingSoundId(u32 soundId) const { return mIsRunning && !mIsFadingOut && GetId() == soundId; } bool isPreparingSoundId(u32 soundId) const { return mIsPreparing && !mIsRunning && GetId() == soundId; } bool isFadingOut() const { return mIsFadingOut && IsAttachedSound(); } bool isPreparingSoundIdWithStartOffset(u32 soundId, u32 offset) const { return isPreparingSoundId(soundId) && (offset == 0 || mPrevStartOffset == offset); } bool hasState() const { return mIsRunning || mIsPreparing || IsAttachedSound(); } bool isPaused() const { return mPauseFlag; } protected: bool isRunning() const { return mIsRunning && IsAttachedSound(); } bool isPreparing() const { return mIsPreparing && !mIsRunning; } void resetControls(); void resetTrackVolumes(); void setControlValue(dSndControlSound_c *ctrl, f32 value, s32 frames); /* 0x08 */ nw4r::ut::Node mBgmMgrNode; /* 0x10 */ u32 mPrevStartOffset; /* 0x14 */ bool mIsPreparing; /* 0x15 */ bool mPauseFlag; /* 0x16 */ bool mIsRunning; /* 0x17 */ bool mIsFadingOut; /* 0x18 */ dSndControlSoundVolume_c mCtrlVolume; /* 0x48 */ dSndControlSoundPitch_c mCtrlPitch; /* 0x78 */ dSndControlSoundPitchLinear_c mLinearPitch; /* 0xAC */ dSndControlSoundSeqTrackVolume_c *mpCtrlSeqTrackVolume; /* 0xB0 */ dSndControlSoundStrmTrackVolume_c *mpCtrlStrmTrackVolume; /* 0xB4 */ dSndControlSoundSeqTempoRatio_c mpCtrlSeqTempoRatio; /* 0xE4 */ nw4r::ut::List mList; }; #endif