NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
snd_AxVoice.h
1#ifndef NW4R_SND_AX_VOICE_H
2#define NW4R_SND_AX_VOICE_H
3
4/*******************************************************************************
5 * headers
6 */
7
8#include <types.h>
9
10#include "nw4r/snd/snd_adpcm.h"
11#include "nw4r/snd/snd_global.h" // SampleFormat
12
13#include "nw4r/ut/ut_LinkList.h"
14
15#include <revolution/AX/AX.h>
16#include <revolution/AX/AXCL.h>
17#include <revolution/AX/AXAlloc.h> // AXSetVoicePriority
18#include <revolution/AX/AXVPB.h>
19
20/*******************************************************************************
21 * classes and functions
22 */
23
24namespace nw4r { namespace snd { namespace detail
25{
26 // [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2ae88
27 class AxVoiceParamBlock
28 {
29 // methods
30 public:
31 // cdtors
32 AxVoiceParamBlock();
33
34 // conversion operators
35 operator AXVPB *() { return mVpb; }
36
37 // methods
38 bool IsAvailable() const { return mVpb != nullptr; }
39 bool IsRun() const
40 {
41 return IsAvailable() && mVpb->pb.state == AX_VOICE_RUN;
42 }
43 ulong GetLoopAddress() const
44 {
45 if (!IsAvailable())
46 return 0;
47
48 return (mVpb->pb.addr.loopAddressHi << 16)
49 + mVpb->pb.addr.loopAddressLo;
50 }
51 ulong GetEndAddress() const
52 {
53 if (!IsAvailable())
54 return 0;
55
56 return (mVpb->pb.addr.endAddressHi << 16)
57 + mVpb->pb.addr.endAddressLo;
58 }
59 ulong GetCurrentAddress() const
60 {
61 if (!IsAvailable())
62 return 0;
63
64 return (mVpb->pb.addr.currentAddressHi << 16)
65 + mVpb->pb.addr.currentAddressLo;
66 }
67 bool IsLpfEnable() const
68 {
69 return IsAvailable() && mVpb->pb.lpf.on == AX_PB_LPF_ON;
70 }
71
72 bool IsBiquadEnable() const
73 {
74 return IsAvailable() && mVpb->pb.biquad.on == AX_PB_BIQUAD_ON;
75 }
76 bool IsRmtIirEnable() const;
77
78 void SetVoiceAddr(AXPBADDR const &addr)
79 {
80 if (!IsAvailable())
81 return;
82
83 // AXSetVoiceAddr doesn't actually modify the object
84 AXSetVoiceAddr(mVpb, const_cast<AXPBADDR *>(&addr));
85 }
86
87 void SetVoicePriority(ulong priority)
88 {
89 if (!IsAvailable())
90 return;
91
92 AXSetVoicePriority(mVpb, priority);
93 }
94 void SetVoiceSrcType(ulong type);
95 void SetVoiceStateRun()
96 {
97 if (!IsAvailable())
98 return;
99
100 AXSetVoiceState(mVpb, AX_VOICE_RUN);
101 }
102 void SetVoiceStateStop()
103 {
104 if (!IsRun())
105 return;
106
107 AXSetVoiceState(mVpb, AX_VOICE_STOP);
108 }
109 void SetVoiceType(u16 type);
110 void SetVoiceMix(AXPBMIX const &mix, bool immediatelySync);
111 void SetVoiceVe(u16 volume, u16 initVolume);
112 void SetVoiceLoop(u16 loop);
113 void SetVoiceLoopAddr(ulong addr);
114 void SetVoiceEndAddr(ulong addr);
115 void SetVoiceAdpcm(AXPBADPCM const &adpcm);
116 void SetVoiceSrc(AXPBSRC const &src);
117 void SetVoiceSrcRatio(f32 ratio);
118 void SetVoiceAdpcmLoop(AXPBADPCMLOOP const &adpcmloop);
119 void SetVoiceLpf(AXPBLPF const &lpf);
120 void SetVoiceLpfCoefs(u16 a0, u16 b0);
121 void SetVoiceBiquad(AXPBBIQUAD const &biquad);
122 void SetVoiceBiquadCoefs(u16 b0, u16 b1, u16 b2, u16 a1, u16 a2);
123 void SetVoiceRmtIIR(__AXPBRMTIIR const &iir);
124 void SetVoiceRmtOn(u16 on);
125 void SetVoiceRmtMix(_AXPBRMTMIX const &iir);
126 void SetVoiceRmtIIRCoefs(u16 type, ...);
127
128 void Set(AXVPB *vpb);
129 void Clear();
130
131 void UpdateDelta();
132 void Sync();
133
134 // static members
135 public:
136 static u16 const DEFAULT_VOLUME = AX_MAX_VOLUME;
137
138 // members
139 private:
140 AXVPB *mVpb; // size 0x04, offset 0x00
141 ulong mSync; // size 0x04, offset 0x04
142 AXPBVE volatile mPrevVeSetting; // size 0x04, offset 0x08
143 bool mFirstVeUpdateFlag; // size 0x01, offset 0x0c
144 /* 1 byte padding */
145 u16 mVolume; // size 0x02, offset 0x0e
146 }; // size 0x10
147
148 // [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2b45f
149 class AxVoice
150 {
151 // enums
152 public:
153 // [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2b187
154 enum AxVoiceCallbackStatus
155 {
156 CALLBACK_STATUS_CANCEL,
157 CALLBACK_STATUS_DROP_DSP,
158 };
159
160 // [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2b23a
161 enum VoiceType
162 {
163 VOICE_TYPE_NORMAL,
164 VOICE_TYPE_STREAM,
165 };
166
167 // [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2b3dd
168 enum SrcType
169 {
170 SRC_NONE,
171 SRC_LINEAR,
172 SRC_4TAP_8K,
173 SRC_4TAP_12K,
174 SRC_4TAP_16K,
175 SRC_4TAP_AUTO,
176 };
177
178 // typedefs
179 public:
180 typedef ut::LinkList<AxVoice, 0x40> LinkList;
181
182 typedef void Callback(AxVoice *dropVoice, AxVoiceCallbackStatus status,
183 void *callbackData);
184
185 // nested types
186 public:
187 // [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2afaa
188 struct MixParam
189 {
190 u16 vL; // size 0x02, offset 0x00
191 u16 vR; // size 0x02, offset 0x02
192 u16 vS; // size 0x02, offset 0x04
193 u16 vAuxAL; // size 0x02, offset 0x06
194 u16 vAuxAR; // size 0x02, offset 0x08
195 u16 vAuxAS; // size 0x02, offset 0x0a
196 u16 vAuxBL; // size 0x02, offset 0x0c
197 u16 vAuxBR; // size 0x02, offset 0x0e
198 u16 vAuxBS; // size 0x02, offset 0x10
199 u16 vAuxCL; // size 0x02, offset 0x12
200 u16 vAuxCR; // size 0x02, offset 0x14
201 u16 vAuxCS; // size 0x02, offset 0x16
202 }; // size 0x18
203
204 // [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2b28a
206 {
207 u16 vMain0; // size 0x02, offset 0x00
208 u16 vAux0; // size 0x02, offset 0x02
209 u16 vMain1; // size 0x02, offset 0x04
210 u16 vAux1; // size 0x02, offset 0x06
211 u16 vMain2; // size 0x02, offset 0x08
212 u16 vAux2; // size 0x02, offset 0x0a
213 u16 vMain3; // size 0x02, offset 0x0c
214 u16 vAux3; // size 0x02, offset 0x0e
215 }; // size 0x10
216
217 // methods
218 public:
219 // cdtors
220 AxVoice();
221 ~AxVoice();
222
223 // methods
224 void Setup(void const *waveAddr, SampleFormat format, int sampleRate);
225
226 SampleFormat GetFormat() const { return mFormat; }
227 ulong GetCurrentPlayingSample() const;
228 ulong GetCurrentPlayingDspAddress() const;
229 ulong GetLoopEndDspAddress() const;
230 f32 GetDspRatio(f32 ratio) const
231 {
232 return ratio * mSampleRate / AX_SAMPLE_RATE;
233 }
234
235 void SetLoopStart(void const *baseAddress, ulong samples);
236 void SetLoopEnd(void const *baseAddress, ulong samples);
237 void SetLoopFlag(bool loopFlag);
238 void SetPriority(ulong priority);
239 void SetVoiceType(VoiceType type);
240 void EnableRemote(bool enable);
241 void ResetDelta();
242 void SetAddr(bool loopFlag, void const *waveAddr, ulong startOffset,
243 ulong loopStart, ulong loopEnd);
244 void SetSrcType(SrcType type, f32 pitch);
245 void SetAdpcm(AdpcmParam const *param);
246 void SetAdpcmLoop(AdpcmLoopParam const *param);
247 bool SetMix(MixParam const &param);
248 void SetRmtMix(const RemoteMixParam &param);
249 void SetSrc(f32 ratio, bool initialUpdate);
250 void SetVe(f32 volume, f32 initVolume);
251 void SetLpf(u16 freq);
252 void SetBiquad(u8 filterType, f32 value);
253 void SetRemoteFilter(u8 filter);
254
255 /* NOTE: covered misspelled as coverd */
256 bool IsDataAddressCoverd(void const *beginAddress,
257 void const *endAddress) const;
258 bool IsNeedNextUpdate(MixParam const &param) const;
259 bool IsPlayFinished() const;
260
261 void Run() { mVpb.SetVoiceStateRun(); }
262 bool IsRun() const { return mVpb.IsRun(); }
263 void Stop() { mVpb.SetVoiceStateStop(); }
264 void StopAtPoint(void const *baseAddress, ulong samples);
265 void Sync() { mVpb.Sync(); }
266
267 static ulong GetDspAddressBySample(void const *baseAddress, ulong samples,
268 SampleFormat format);
269 static ulong GetSampleByDspAddress(void const *baseAddress, ulong addr,
270 SampleFormat format);
271
272 static u16 GetAxFormatFromSampleFormat(SampleFormat sampleFormat);
273
274 static void CalcOffsetAdpcmParam(u16 *outPredScale, u16 *outYn1,
275 u16 *outYn2, ulong offset,
276 const void *dataAddr,
277 AdpcmParam const &adpcmParam);
278
279 private:
280 // callbacks
281 static void VoiceCallback(void *callbackData);
282
283 // static members
284 public:
285 static u16 const VOICE_GAIN_MAX;
286
287 // methods
288 private:
289 AxVoiceParamBlock mVpb; // size 0x10, offset 0x00
290 void const *mWaveData; // size 0x04, offset 0x10
291 SampleFormat mFormat; // size 0x04, offset 0x14
292 int mSampleRate; // size 0x04, offset 0x18
293 bool mFirstMixUpdateFlag; // size 0x01, offset 0x1c
294 bool mReserveForFreeFlag; // size 0x01, offset 0x1d
295 /* 2 bytes padding */
296 MixParam mMixPrev; // size 0x18, offset 0x20
297 Callback *mCallback; // size 0x04, offset 0x38
298 void *mCallbackData; // size 0x04, offset 0x3c
299 public:
300 ut::LinkListNode node; // size 0x08, offset 0x40
301
302 // friends
303 private:
304 friend class AxVoiceManager;
305 }; // size 0x48
306}}} // namespace nw4r::snd::detail
307
308#endif // NW4R_SND_AX_VOICE_H