summaryrefslogtreecommitdiff
path: root/include/nw4r/snd/snd_Channel.h
blob: 20a340779e7a70e7d75ade21dc93e523e30a1473 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#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