15 alure::Array
<ALubyte
,16> mGuid
;
16 using char16
= char[16];
19 inline bool operator==(const IDType::char16
&lhs
, const IDType
&rhs
)
21 auto liter
= std::begin(lhs
);
22 for(ALubyte c
: rhs
.mGuid
)
24 if(liter
== std::end(lhs
) || c
!= *liter
)
27 return (liter
== std::end(lhs
));
30 const IDType SUBTYPE_PCM
{{{
31 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
32 0x00, 0x38, 0x9b, 0x71
34 const IDType SUBTYPE_FLOAT
{{{
35 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
36 0x00, 0x38, 0x9b, 0x71
39 const IDType SUBTYPE_BFORMAT_PCM
{{{
40 0x01, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
41 0xca, 0x00, 0x00, 0x00
43 const IDType SUBTYPE_BFORMAT_FLOAT
{{{
44 0x03, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
45 0xca, 0x00, 0x00, 0x00
48 constexpr int CHANNELS_MONO
= 0x04;
49 constexpr int CHANNELS_STEREO
= 0x01 | 0x02;
50 constexpr int CHANNELS_QUAD
= 0x01 | 0x02 | 0x10 | 0x20;
51 constexpr int CHANNELS_5DOT1
= 0x01 | 0x02 | 0x04 | 0x08 | 0x200 | 0x400;
52 constexpr int CHANNELS_5DOT1_REAR
= 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20;
53 constexpr int CHANNELS_6DOT1
= 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400;
54 constexpr int CHANNELS_7DOT1
= 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x200 | 0x400;
57 static ALuint
read_le32(std::istream
&stream
)
60 if(!stream
.read(buf
, sizeof(buf
)) || stream
.gcount() != sizeof(buf
))
62 return ((ALuint(buf
[0] )&0x000000ff) | (ALuint(buf
[1]<< 8)&0x0000ff00) |
63 (ALuint(buf
[2]<<16)&0x00ff0000) | (ALuint(buf
[3]<<24)&0xff000000));
66 static ALushort
read_le16(std::istream
&stream
)
69 if(!stream
.read(buf
, sizeof(buf
)) || stream
.gcount() != sizeof(buf
))
71 return ((ALushort(buf
[0] )&0x00ff) | (ALushort(buf
[1]<<8)&0xff00));
79 class WaveDecoder final
: public Decoder
{
80 UniquePtr
<std::istream
> mFile
;
82 ChannelConfig mChannelConfig
;
83 SampleType mSampleType
;
87 // In sample frames, relative to sample data start
88 std::pair
<ALuint
,ALuint
> mLoopPts
;
90 // In bytes from beginning of file
91 std::istream::pos_type mStart
, mEnd
;
94 WaveDecoder(UniquePtr
<std::istream
> file
, ChannelConfig channels
, SampleType type
, ALuint frequency
, ALuint framesize
,
95 std::istream::pos_type start
, std::istream::pos_type end
, ALuint loopstart
, ALuint loopend
)
96 : mFile(std::move(file
)), mChannelConfig(channels
), mSampleType(type
), mFrequency(frequency
)
97 , mFrameSize(framesize
), mLoopPts
{loopstart
,loopend
}, mStart(start
), mEnd(end
)
99 ~WaveDecoder() override
;
101 ALuint
getFrequency() const override
;
102 ChannelConfig
getChannelConfig() const override
;
103 SampleType
getSampleType() const override
;
105 uint64_t getLength() const override
;
106 bool seek(uint64_t pos
) override
;
108 std::pair
<uint64_t,uint64_t> getLoopPoints() const override
;
110 ALuint
read(ALvoid
*ptr
, ALuint count
) override
;
113 WaveDecoder::~WaveDecoder()
118 ALuint
WaveDecoder::getFrequency() const
123 ChannelConfig
WaveDecoder::getChannelConfig() const
125 return mChannelConfig
;
128 SampleType
WaveDecoder::getSampleType() const
134 uint64_t WaveDecoder::getLength() const
136 return (mEnd
- mStart
) / mFrameSize
;
139 bool WaveDecoder::seek(uint64_t pos
)
141 std::streamsize offset
= pos
*mFrameSize
+ mStart
;
143 if(offset
> mEnd
|| !mFile
->seekg(offset
))
148 std::pair
<uint64_t,uint64_t> WaveDecoder::getLoopPoints() const
153 ALuint
WaveDecoder::read(ALvoid
*ptr
, ALuint count
)
157 auto pos
= mFile
->tellg();
158 size_t len
= count
* mFrameSize
;
163 len
= std::min
<std::istream::pos_type
>(len
, mEnd
-pos
);
164 #ifdef __BIG_ENDIAN__
167 case SampleType::Float32
:
168 while(total
< len
&& mFile
->good() && !mFile
->eof())
171 size_t todo
= std::min(len
-total
, sizeof(temp
));
173 mFile
->read(temp
, todo
);
174 std::streamsize got
= mFile
->gcount();
176 for(std::streamsize i
= 0;i
< got
;++i
)
177 reinterpret_cast<char*>(ptr
)[total
+i
] = temp
[i
^3];
184 case SampleType::Int16
:
185 while(total
< len
&& mFile
->good() && !mFile
->eof())
188 size_t todo
= std::min(len
-total
, sizeof(temp
));
190 mFile
->read(temp
, todo
);
191 std::streamsize got
= mFile
->gcount();
193 for(std::streamsize i
= 0;i
< got
;++i
)
194 reinterpret_cast<char*>(ptr
)[total
+i
] = temp
[i
^1];
201 case SampleType::UInt8
:
202 case SampleType::Mulaw
:
206 mFile
->read(reinterpret_cast<char*>(ptr
), len
);
207 total
= mFile
->gcount() / mFrameSize
;
215 SharedPtr
<Decoder
> WaveDecoderFactory::createDecoder(UniquePtr
<std::istream
> &file
)
217 ChannelConfig channels
= ChannelConfig::Mono
;
218 SampleType type
= SampleType::UInt8
;
219 ALuint frequency
= 0;
220 ALuint framesize
= 0;
221 ALuint loop_pts
[2]{0, 0};
222 ALuint blockalign
= 0;
223 ALuint framealign
= 0;
226 if(!file
->read(tag
, 4) || file
->gcount() != 4 || memcmp(tag
, "RIFF", 4) != 0)
228 ALuint totalsize
= read_le32(*file
) & ~1u;
229 if(!file
->read(tag
, 4) || file
->gcount() != 4 || memcmp(tag
, "WAVE", 4) != 0)
232 while(file
->good() && !file
->eof() && totalsize
> 8)
234 if(!file
->read(tag
, 4) || file
->gcount() != 4)
236 ALuint size
= read_le32(*file
);
237 if(size
< 2) return nullptr;
240 size
= std::min((size
+1) & ~1u, totalsize
);
243 if(memcmp(tag
, "fmt ", 4) == 0)
245 /* 'fmt ' tag needs at least 16 bytes. */
246 if(size
< 16) goto next_chunk
;
249 ALushort fmttype
= read_le16(*file
); size
-= 2;
251 /* mono or stereo data */
252 int chancount
= read_le16(*file
); size
-= 2;
254 /* sample frequency */
255 frequency
= read_le32(*file
); size
-= 4;
257 /* skip average bytes per second */
258 read_le32(*file
); size
-= 4;
260 /* bytes per block */
261 blockalign
= read_le16(*file
); size
-= 2;
263 /* bits per sample */
264 int bitdepth
= read_le16(*file
); size
-= 2;
266 /* Look for any extra data and try to find the format */
267 ALuint extrabytes
= 0;
270 extrabytes
= read_le16(*file
);
273 extrabytes
= std::min
<ALuint
>(extrabytes
, size
);
275 /* Format type should be 0x0001 for integer PCM data, 0x0003 for
276 * float PCM data, 0x0007 for muLaw, and 0xFFFE extensible data.
278 if(fmttype
== 0x0001)
281 channels
= ChannelConfig::Mono
;
282 else if(chancount
== 2)
283 channels
= ChannelConfig::Stereo
;
288 type
= SampleType::UInt8
;
289 else if(bitdepth
== 16)
290 type
= SampleType::Int16
;
294 else if(fmttype
== 0x0003)
297 channels
= ChannelConfig::Mono
;
298 else if(chancount
== 2)
299 channels
= ChannelConfig::Stereo
;
304 type
= SampleType::Float32
;
308 else if(fmttype
== 0x0007)
311 channels
= ChannelConfig::Mono
;
312 else if(chancount
== 2)
313 channels
= ChannelConfig::Stereo
;
318 type
= SampleType::Mulaw
;
322 else if(fmttype
== 0xFFFE)
328 ALushort validbits
= read_le16(*file
); size
-= 2;
329 ALuint chanmask
= read_le32(*file
); size
-= 4;
330 file
->read(subtype
, 16); size
-= file
->gcount();
332 /* Padded bit depths not supported */
333 if(validbits
!= bitdepth
)
336 if(subtype
== SUBTYPE_BFORMAT_PCM
|| subtype
== SUBTYPE_BFORMAT_FLOAT
)
342 channels
= ChannelConfig::BFormat2D
;
343 else if(chancount
== 4)
344 channels
= ChannelConfig::BFormat3D
;
348 else if(subtype
== SUBTYPE_PCM
|| subtype
== SUBTYPE_FLOAT
)
350 if(chancount
== 1 && chanmask
== CHANNELS_MONO
)
351 channels
= ChannelConfig::Mono
;
352 else if(chancount
== 2 && chanmask
== CHANNELS_STEREO
)
353 channels
= ChannelConfig::Stereo
;
354 else if(chancount
== 4 && chanmask
== CHANNELS_QUAD
)
355 channels
= ChannelConfig::Quad
;
356 else if(chancount
== 6 && (chanmask
== CHANNELS_5DOT1
|| chanmask
== CHANNELS_5DOT1_REAR
))
357 channels
= ChannelConfig::X51
;
358 else if(chancount
== 7 && chanmask
== CHANNELS_6DOT1
)
359 channels
= ChannelConfig::X61
;
360 else if(chancount
== 8 && chanmask
== CHANNELS_7DOT1
)
361 channels
= ChannelConfig::X71
;
366 if(subtype
== SUBTYPE_PCM
|| subtype
== SUBTYPE_BFORMAT_PCM
)
369 type
= SampleType::UInt8
;
370 else if(bitdepth
== 16)
371 type
= SampleType::Int16
;
375 else if(subtype
== SUBTYPE_FLOAT
|| subtype
== SUBTYPE_BFORMAT_FLOAT
)
378 type
= SampleType::Float32
;
388 framesize
= FramesToBytes(1, channels
, type
);
390 /* Calculate the number of frames per block (ADPCM will need extra
392 framealign
= blockalign
/ framesize
;
394 else if(memcmp(tag
, "smpl", 4) == 0)
396 /* sampler data needs at least 36 bytes */
397 if(size
< 36) goto next_chunk
;
399 /* Most of this only affects MIDI sampling, but we only care about
400 * the loop definitions at the end. */
401 /*ALuint manufacturer =*/ read_le32(*file
);
402 /*ALuint product =*/ read_le32(*file
);
403 /*ALuint smpperiod =*/ read_le32(*file
);
404 /*ALuint unitynote =*/ read_le32(*file
);
405 /*ALuint pitchfrac =*/ read_le32(*file
);
406 /*ALuint smptefmt =*/ read_le32(*file
);
407 /*ALuint smpteoffset =*/ read_le32(*file
);
408 ALuint loopcount
= read_le32(*file
);
409 /*ALuint extrabytes =*/ read_le32(*file
);
412 for(ALuint i
= 0;i
< loopcount
&& size
>= 24;++i
)
414 /*ALuint id =*/ read_le32(*file
);
415 ALuint type
= read_le32(*file
);
416 ALuint loopstart
= read_le32(*file
);
417 ALuint loopend
= read_le32(*file
);
418 /*ALuint frac =*/ read_le32(*file
);
419 ALuint numloops
= read_le32(*file
);
422 /* Only handle indefinite forward loops. */
423 if(type
== 0 || numloops
== 0)
425 loop_pts
[0] = loopstart
;
426 loop_pts
[1] = loopend
;
431 else if(memcmp(tag
, "data", 4) == 0)
433 if(framesize
== 0 || !Context::GetCurrent().isSupported(channels
, type
))
436 /* Make sure there's at least one sample frame of audio data. */
437 std::istream::pos_type start
= file
->tellg();
438 std::istream::pos_type end
= start
+ std::istream::pos_type(size
- (size
%framesize
));
439 if(end
-start
>= framesize
)
441 /* Loop points are byte offsets relative to the data start.
442 * Convert to sample frame offsets. */
443 return MakeShared
<WaveDecoder
>(std::move(file
),
444 channels
, type
, frequency
, framesize
, start
, end
,
445 loop_pts
[0] / blockalign
* framealign
,
446 loop_pts
[1] / blockalign
* framealign