summaryrefslogtreecommitdiff
path: root/include/nw4r/snd/snd_StrmFile.h
blob: 2bfdcbf720cc5c925710a952a27e766a9f322c10 (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
#ifndef NW4R_SND_STRM_FILE_H
#define NW4R_SND_STRM_FILE_H

/*******************************************************************************
 * headers
 */

#include "common.h"

#include "nw4r/snd/snd_adpcm.h"
#include "nw4r/snd/snd_global.h" // SampleFormat
#include "nw4r/snd/snd_Util.h" // Util::DataRef

#include "nw4r/ut/ut_binaryFileFormat.h"

/*******************************************************************************
 * types
 */

// forward declarations
namespace nw4r { namespace ut { class FileStream; }}

namespace nw4r { namespace snd { namespace detail
{
	struct StrmFile
	{
		/* Header */

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f271d
		struct Header
		{
			ut::BinaryFileHeader	fileHeader;			// size 0x10, offset 0x00
			u32						headBlockOffset;	// size 0x04, offset 0x10
			u32						headBlockSize;		// size 0x04, offset 0x14
			u32						adpcBlockOffset;	// size 0x04, offset 0x18
			u32						adpcBlockSize;		// size 0x04, offset 0x1c
			u32						dataBlockOffset;	// size 0x04, offset 0x20
			u32						dataBlockSize;		// size 0x04, offset 0x24
		}; // size 0x28

		/* HeadBlock */

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f2d81
		struct StrmDataInfo
		{
			u8	format;					// size 0x01, offset 0x00
			u8	loopFlag;				// size 0x01, offset 0x01
			u8	numChannels;			// size 0x01, offset 0x02
			u8	sampleRate24;			// size 0x01, offset 0x03
			u16	sampleRate;				// size 0x02, offset 0x04
			u16	blockHeaderOffset;		// size 0x02, offset 0x06
			u32	loopStart;				// size 0x04, offset 0x08
			u32	loopEnd;				// size 0x04, offset 0x0c
			u32	dataOffset;				// size 0x04, offset 0x10
			u32	numBlocks;				// size 0x04, offset 0x14
			u32	blockSize;				// size 0x04, offset 0x18
			u32	blockSamples;			// size 0x04, offset 0x1c
			u32	lastBlockSize;			// size 0x04, offset 0x20
			u32	lastBlockSamples;		// size 0x04, offset 0x24
			u32	lastBlockPaddedSize;	// size 0x04, offset 0x28
			u32	adpcmDataInterval;		// size 0x04, offset 0x2c
			u32	adpcmDataSize;			// size 0x04, offset 0x30
		}; // size 0x34

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f3a1e
		struct TrackInfo
		{
			u8	channelCount;			// size 0x01, offset 0x00
			u8	channelIndexTable[];	// flexible,  offset 0x01 (unit size 0x01)
		}; // size 0x01

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f3196
		struct TrackInfoEx
		{
			u8		volume;					// size 0x01, offset 0x00
			u8		pan;					// size 0x01, offset 0x01
			u8	padding[2];
			u32	reserved;
			u8		channelCount;			// size 0x01, offset 0x08
			u8		channelIndexTable[];	// flexible,  offset 0x09 (unit size 0x01)
			/* 3 bytes padding */
		}; // size 0x0c

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f34ef
		struct TrackTable
		{
			u8										trackCount;			// size 0x01, offset 0x00
			u8										trackDataType;		// size 0x01, offset 0x01
			u8									padding[2];
			Util::DataRef<TrackInfo, TrackInfoEx>	refTrackHeader[];	// flexible,  offset 0x04 (unit size 0x08)
		}; // size 0x04

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f336f
		struct AdpcmParamSet
		{
			AdpcmParam		adpcmParam;		// size 0x28, offset 0x00
			AdpcmLoopParam	adpcmLoopParam;	// size 0x06, offset 0x28
		}; // size 0x2e

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f3cbb
		struct ChannelInfo
		{
			Util::DataRef<AdpcmParamSet>	refAdpcmInfo;	// size 0x08, offset 0x00
		}; // size 0x08

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f3780
		struct ChannelTable
		{
			u8							channelCount;		// size 0x01, offset 0x00
			u8						padding[3];
			Util::DataRef<ChannelInfo>	refChannelHeader[];	// flexible,  offset 0x04 (unit size 0x08)
		}; // size 0x04

		static u32 const SIGNATURE_HEAD_BLOCK =
			NW4R_FOUR_BYTE('H', 'E', 'A', 'D');

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f2ab0
		struct HeadBlock
		{
			ut::BinaryBlockHeader		blockHeader;		// size 0x08, offset 0x00
			Util::DataRef<StrmDataInfo>	refDataHeader;		// size 0x08, offset 0x08
			Util::DataRef<TrackTable>	refTrackTable;		// size 0x08, offset 0x10
			Util::DataRef<ChannelTable>	refChannelTable;	// size 0x08, offset 0x18
		}; // size 0x20

		/* StrmFile */

		static u32 const SIGNATURE_FILE =
			NW4R_FOUR_BYTE('R', 'S', 'T', 'M');
		static int const FILE_VERSION = NW4R_FILE_VERSION(1, 0);
	}; // "namespace" StrmFile
}}} // namespace nw4r::snd::detail

/*******************************************************************************
 * classes and functions
 */

namespace nw4r { namespace snd { namespace detail
{
	// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f2b8e
	class StrmFileReader
	{
	// nested types
	public:
		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f0e7
		struct StrmInfo
		{
			SampleFormat	sampleFormat;			// size 0x04, offset 0x00
			bool			loopFlag;				// size 0x01, offset 0x04
			/* 3 bytes padding */
			int				numChannels;			// size 0x04, offset 0x08
			int				sampleRate;				// size 0x04, offset 0x0c
			u16				blockHeaderOffset;		// size 0x02, offset 0x10
			/* 2 bytes padding */
			u32				loopStart;				// size 0x04, offset 0x14
			u32				loopEnd;				// size 0x04, offset 0x18
			u32				dataOffset;				// size 0x04, offset 0x1c
			u32				numBlocks;				// size 0x04, offset 0x20
			u32				blockSize;				// size 0x04, offset 0x24
			u32				blockSamples;			// size 0x04, offset 0x28
			u32				lastBlockSize;			// size 0x04, offset 0x2c
			u32				lastBlockSamples;		// size 0x04, offset 0x30
			u32				lastBlockPaddedSize;	// size 0x04, offset 0x34
			u32				adpcmDataInterval;		// size 0x04, offset 0x38
			u32				adpcmDataSize;			// size 0x04, offset 0x3c
		}; // size 0x40

		// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2fa44
		struct StrmTrackInfo
		{
			u8	volume;					// size 0x01, offset 0x00
			u8	pan;					// size 0x01, offset 0x01
			/* 2 bytes padding */
			int	channelCount;			// size 0x04, offset 0x04
			u8	channelIndexTable[32];	// size 0x20, offset 0x08
		}; // size 0x28

	// methods
	public:
		// cdtors
		StrmFileReader();

		// methods
		void Setup(void const *strmData);

		bool IsAvailable() const { return mHeader != nullptr; }
		u32 GetAdpcBlockOffset() const
		{
			if (IsAvailable())
				return mHeader->adpcBlockOffset;

			return 0;
		}

		int GetTrackCount() const;
		int GetChannelCount() const;

		bool ReadStrmInfo(StrmInfo *strmInfo) const;
		bool ReadStrmTrackInfo(StrmTrackInfo *trackInfo, int trackIndex) const;
		bool ReadAdpcmInfo(AdpcmParam *adpcmParam,
		                   AdpcmLoopParam *adpcmLoopParam,
		                   int channelIndex) const;

	private:
		static bool IsValidFileHeader(void const *strmData);

		static SampleFormat GetSampleFormatFromStrmFileFormat(u8 format);

	// static members
	public:
		static int const SUPPORTED_FILE_VERSION = NW4R_FILE_VERSION(1, 0);

	// members
	private:
		StrmFile::Header	const *mHeader;		// size 0x04, offset 0x00
		StrmFile::HeadBlock	const *mHeadBlock;	// size 0x04, offset 0x04

	// friends
	private:
		friend class StrmFileLoader;
	}; // size 0x08

	// [R89JEL]:/bin/RVL/Debug/mainD.elf:.debug::0x2f3fc4
	class StrmFileLoader
	{
	// methods
	public:
		// cdtors
		StrmFileLoader(ut::FileStream &stream) : mStream(stream) {}

		// methods
		bool LoadFileHeader(void *buffer, u32 size);

		int GetTrackCount() const;
		int GetChannelCount() const;

		bool ReadStrmInfo(StrmFileReader::StrmInfo *strmInfo) const;
		bool ReadStrmTrackInfo(StrmFileReader::StrmTrackInfo *trackInfo,
		                       int trackIndex) const;
		bool ReadAdpcmInfo(AdpcmParam *adpcmParam,
		                   AdpcmLoopParam *adpcmLoopParam,
		                   int channelIndex) const;
		bool ReadAdpcBlockData(u16 *yn1, u16 *yn2, int blockIndex,
		                       int channelCount);

	// members
	private:
		ut::FileStream	&mStream;	// size 0x04, offset 0x00
		StrmFileReader	mReader;	// size 0x08, offset 0x04
	}; // size 0x0c
}}} // namespace nw4r::snd::detail

#endif // NW4R_SND_STRM_FILE_H