summaryrefslogtreecommitdiff
path: root/libs/revolution/src/homebuttonLib/nw4hbm/snd/StrmPlayer.h
blob: eae08ba82d6e4b53e6ea4d2ccb4a7ce24d29197f (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
#ifndef NW4HBM_SND_STRM_PLAYER_H
#define NW4HBM_SND_STRM_PLAYER_H

#include "snd_types.h"

#include "AxVoice.h"

//! TODO: find a way to remove this hack
#define MAKE_DTOR_ZERO
#include "BasicPlayer.h"
#undef MAKE_DTOR_ZERO

#include "InstancePool.h"
#include "StrmChannel.h"
#include "StrmFile.h"

namespace nw4hbm {
    namespace snd {
        namespace detail {

            class StrmPlayer : public BasicPlayer {
            public:
                typedef enum StartOffsetType {
                    START_OFFSET_TYPE_SAMPLE = 0,
                    START_OFFSET_TYPE_MILLISEC
                } StartOffsetType;

                typedef struct StrmHeader {
                    //! TODO: Why 8 if the player only supports 2???
                    static const int STRM_CHANNEL_MAX = 8;

                    /* 0x00 */ StrmInfo strmInfo;
                    /* 0x38 */ AdpcmInfo adpcmInfo[STRM_CHANNEL_MAX];
                } StrmHeader;

                //! TODO: How is this calculated?
                static const int LOAD_BUFFER_SIZE = 0x4000 + 32;
                class LoadCommand {
                    friend class StrmPlayer;

                public:
                    virtual void NotifyAsyncEnd(bool result);

                    void SetAdpcmLoopContext(int channelNum, u16* predScale);
                    void* GetBuffer(int channelNum);

                private:
                    typedef enum Status {
                        STATE_SETUP = 0,
                        STATE_INTERVAL,
                    } Status;

                    /* 0x04 */ StrmPlayer* mPlayer;
                    /* 0x08 */ Status mStatus;
                    /* 0x0C */ s32 mStreamBlockIndex;
                    /* 0x10 */ s32 mBufferBlockIndex;

                public:
                    /* 0x14 */ ut::LinkListNode mLinkNode;

                    static u8 mMramBuf[LOAD_BUFFER_SIZE] ATTRIBUTE_ALIGN(32);
                };
                typedef ut::LinkList<LoadCommand, offsetof(LoadCommand, mLinkNode)> LoadCommandList;

                typedef void (*NotifyLoadHeaderAsyncEndCallback)(bool, const StrmHeader*, void*);
                class StrmCallback {
                public:
                    typedef enum Result {
                        RESULT_SUCCESS = 0,
                        RESULT_FAILED,
                        RESULT_CANCELED,
                        RESULT_ASYNC,
                        RESULT_RETRY
                    } Result;

                    virtual ~StrmCallback() {}

                    virtual Result LoadHeader(StrmPlayer::NotifyLoadHeaderAsyncEndCallback callback,
                                              void* callbackData, u32 userId,
                                              u32 userData) const = 0;
                    virtual Result LoadStream(void* mramAddr, u32 size, s32 offset, int numChannels,
                                              u32 blockSize, s32 blockHeaderOffset,
                                              bool needUpdateAdpcmLoop,
                                              StrmPlayer::LoadCommand& callback, u32 userId,
                                              u32 userData) const = 0;

                    virtual void CancelLoading(u32 userId, u32 userData) const = 0;
                };

            public:
                StrmPlayer();

                /* 0x0C */ virtual bool Start();
                /* 0x10 */ virtual void Stop();
                /* 0x14 */ virtual void Pause(bool flag);
                /* 0x18 */ virtual bool IsActive() const { return mActiveFlag; }
                /* 0x1C */ virtual bool IsPrepared() const { return mPreparedFlag; };
                /* 0x20 */ virtual bool IsStarted() const { return mStartedFlag; };
                /* 0x24 */ virtual bool IsPause() const { return mPauseFlag; };
                /* 0x28 */ virtual void SetVolume(f32 volume) { mExtVolume = volume; }
                /* 0x2C */ virtual void SetPitch(f32 pitch) { mExtPitch = pitch; }
                /* 0x30 */ virtual void SetPan(f32 pan) { mExtPan = pan; }
                /* 0x34 */ virtual void SetSurroundPan(f32 surroundPan) {
                    mExtSurroundPan = surroundPan;
                }
                /* 0x38 */ virtual void SetPan2(f32 pan2) { mExtPan2 = pan2; }
                /* 0x3C */ virtual void SetSurroundPan2(f32 surroundPan2) {
                    mExtSurroundPan2 = surroundPan2;
                }
                /* 0x40 */ virtual void SetLpfFreq(f32 lpfFreq) { mExtLpfFreq = lpfFreq; }
                /* 0x44 */ virtual f32 GetVolume() const { return mExtVolume; };
                /* 0x48 */ virtual f32 GetPitch() const { return mExtPitch; };
                /* 0x4C */ virtual f32 GetPan() const { return mExtPan; };
                /* 0x50 */ virtual f32 GetSurroundPan() const { return mExtSurroundPan; };
                /* 0x54 */ virtual f32 GetPan2() const { return mExtPan2; };
                /* 0x58 */ virtual f32 GetSurroundPan2() const { return mExtSurroundPan2; };
                /* 0x5C */ virtual f32 GetLpfFreq() const { return mExtLpfFreq; };
                /* 0x60 */ virtual void SetOutputLine(int lineFlag);
                /* 0x64 */ virtual void SetMainOutVolume(f32 volume);
                /* 0x68 */ virtual void SetMainSend(f32 send);
                /* 0x6C */ virtual void SetFxSend(AuxBus bus, f32 send);
                /* 0x70 */ virtual void SetRemoteOutVolume(int remoteIndex, f32 volume);
                /* 0x74 */ virtual void SetRemoteSend(int remoteIndex, f32 send);
                /* 0x78 */ virtual void SetRemoteFxSend(int remoteIndex, f32 send);
                /* 0x7C */ virtual int GetOutputLine() const;
                /* 0x80 */ virtual f32 GetMainOutVolume() const;
                /* 0x84 */ virtual f32 GetMainSend() const;
                /* 0x88 */ virtual f32 GetFxSend(AuxBus bus) const;
                /* 0x8C */ virtual f32 GetRemoteOutVolume(int remoteIndex) const;
                /* 0x90 */ virtual f32 GetRemoteSend(int remoteIndex) const;
                /* 0x94 */ virtual f32 GetRemoteFxSend(int remoteIndex) const;

                void Setup(const StrmHeader* header);
                bool SetupPlayer(const StrmHeader* header);
                void Shutdown();

                bool Prepare(StrmBufferPool* bufferPool, StartOffsetType startOffsetType,
                             s32 startOffset, int voices, StrmCallback* callback, u32 callbackData);

                void InitParam(int voices);
                void ForceStop();

                void Update();

                static void UpdateAllPlayers();
                static void StopAllPlayers();
                static void UpdateBufferAllPlayers();

            private:
                static const int DATA_BLOCK_COUNT_MIN = 4;
                static const int DATA_BLOCK_COUNT_MAX = 32;
                static const int DATA_BLOCK_SIZE_MAX = 0x2000;

                bool AllocChannels(int channels, int voices);
                void FreeChannels();

                void UpdateBuffer();
                void UpdateLoopAddress(u32 startSample, u32 endSample);
                void UpdatePlayingBlockIndex();
                void UpdateDataLoopAddress(s32 endBlock);
                void SetLoopEndToZeroBuffer(int endBlock);
                void UpdateLoadingBlockIndex(LoadCommand::Status status);
                void UpdatePauseStatus();

                int CalcLoadingBufferBlockCount() const;
                bool CalcStartOffset(s32* blockIndex, u32* blockOffset, s32* loopCount);

                static void VoiceCallbackFunc(AxVoice* voice, AxVoice::CallbackStatus status,
                                              void* pCallbackArg);

                static void NotifyStrmHeaderAsyncEndCallback(bool result, const StrmHeader* header,
                                                             void* userData);

            public:
                /* 0x008 */ ut::LinkListNode mPlayerLink;

            private:
                /* 0x010 */ StrmInfo mStrmInfo;
                /* 0x048 */ u8 mActiveFlag;
                /* 0x049 */ u8 mStartedFlag;
                /* 0x04A */ u8 mPreparedFlag;
                /* 0x04B */ u8 mPauseFlag;
                /* 0x04C */ u8 mDiskErrorFlag;
                /* 0x04D */ u8 mPauseStatus;
                /* 0x04E */ u8 mLoadWaitFlag;
                /* 0x04F */ u8 mNoRealtimeLoadFlag;
                /* 0x050 */ u8 mSkipUpdateAdpcmLoop;
                /* 0x051 */ u8 mValidAdpcmLoop;
                /* 0x052 */ u8 mPlayFinishFlag;
                /* 0x053 */ u8 mLoadFinishFlag;
                /* 0x054 */ s32 mLoopCounter;
                /* 0x058 */ int mPrepareCounter;
                /* 0x05C */ int mChangeNumBlocks;
                /* 0x060 */ int mDataBlockSize;
                /* 0x064 */ int mBufferBlockCount;
                /* 0x068 */ int mBufferBlockCountBase;
                /* 0x06C */ int mLoadingBufferBlockCount;
                /* 0x070 */ int mLoadingBufferBlockIndex;
                /* 0x074 */ int mLoadingDataBlockIndex;
                /* 0x078 */ int mPlayingBufferBlockCount;
                /* 0x07C */ int mPlayingBufferBlockIndex;
                /* 0x080 */ int mPlayingDataBlockIndex;
                /* 0x084 */ int mLoopStartBlockIndex;
                /* 0x088 */ int mLastBlockIndex;
                /* 0x08C */ StartOffsetType mStartOffsetType;
                /* 0x090 */ int mStartOffset;
                /* 0x094 */ LoadCommandList mFreeLoadCommandList;
                /* 0x0A0 */ LoadCommandList mFillBufferCommandList;
                /* 0x0AC */ LoadCommand mLoadCoammndArray[32];
                /* 0x42C */ StrmBufferPool* mBufferPool;
                /* 0x430 */ StrmCallback* mCallback;
                /* 0x434 */ u32 mCallbackData;
                /* 0x438 */ AxVoice* mVoice;
                /* 0x43C */ f32 mExtVolume;
                /* 0x440 */ f32 mExtPan;
                /* 0x444 */ f32 mExtSurroundPan;
                /* 0x448 */ f32 mExtPan2;
                /* 0x44C */ f32 mExtSurroundPan2;
                /* 0x450 */ f32 mExtPitch;
                /* 0x454 */ f32 mExtLpfFreq;
                /* 0x458 */ int mOutputLineFlag;
                /* 0x45C */ f32 mMainOutVolume;
                /* 0x460 */ f32 mMainSend;
                /* 0x464 */ f32 mFxSend[AUX_BUS_NUM];
                /* 0x470 */ f32 mRemoteOutVolume[WPAD_MAX_CONTROLLERS];
                /* 0x480 */ f32 mRemoteSend[WPAD_MAX_CONTROLLERS];
                /* 0x490 */ f32 mRemoteFxSend[WPAD_MAX_CONTROLLERS];
                /* 0x4A0 */ s32 mChannelCount;
                /* 0x4A4 */ s32 mVoiceOutCount;
                /* 0x4A8 */ StrmChannel mChannels[CHANNEL_MAX];
                /* 0x518 */ u16 mAdpcmPredScale[CHANNEL_MAX];
            };

            typedef ut::LinkList<StrmPlayer, offsetof(StrmPlayer, mPlayerLink)> StrmPlayerList;

        }  // namespace detail
    }  // namespace snd
}  // namespace nw4hbm

#endif