14 static const ALubyte SUBTYPE_PCM
[] = {
15 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
16 0x00, 0x38, 0x9b, 0x71
18 static const ALubyte SUBTYPE_FLOAT
[] = {
19 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
20 0x00, 0x38, 0x9b, 0x71
23 static const ALubyte SUBTYPE_BFORMAT_PCM
[] = {
24 0x01, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
25 0xca, 0x00, 0x00, 0x00
27 static const ALubyte SUBTYPE_BFORMAT_FLOAT
[] = {
28 0x03, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
29 0xca, 0x00, 0x00, 0x00
32 static const int CHANNELS_MONO
= 0x04;
33 static const int CHANNELS_STEREO
= 0x01 | 0x02;
34 static const int CHANNELS_QUAD
= 0x01 | 0x02 | 0x10 | 0x20;
35 static const int CHANNELS_5DOT1
= 0x01 | 0x02 | 0x04 | 0x08 | 0x200 | 0x400;
36 static const int CHANNELS_5DOT1_REAR
= 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20;
37 static const int CHANNELS_6DOT1
= 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400;
38 static const int CHANNELS_7DOT1
= 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x200 | 0x400;
41 static ALuint
read_le32(std::istream
&stream
)
44 if(!stream
.read(buf
, sizeof(buf
)) || stream
.gcount() != sizeof(buf
))
46 return ((ALuint(buf
[0] )&0x000000ff) | (ALuint(buf
[1]<< 8)&0x0000ff00) |
47 (ALuint(buf
[2]<<16)&0x00ff0000) | (ALuint(buf
[3]<<24)&0xff000000));
50 static ALushort
read_le16(std::istream
&stream
)
53 if(!stream
.read(buf
, sizeof(buf
)) || stream
.gcount() != sizeof(buf
))
55 return ((ALushort(buf
[0] )&0x00ff) | (ALushort(buf
[1]<<8)&0xff00));
59 class WaveDecoder
: public Decoder
{
60 UniquePtr
<std::istream
> mFile
;
62 ChannelConfig mChannelConfig
;
63 SampleType mSampleType
;
67 // In sample frames, relative to sample data start
68 std::pair
<ALuint
,ALuint
> mLoopPts
;
70 // In bytes from beginning of file
71 std::istream::pos_type mStart
, mEnd
;
74 WaveDecoder(UniquePtr
<std::istream
> file
, ChannelConfig channels
, SampleType type
, ALuint frequency
, ALuint framesize
,
75 std::istream::pos_type start
, std::istream::pos_type end
, ALuint loopstart
, ALuint loopend
)
76 : mFile(std::move(file
)), mChannelConfig(channels
), mSampleType(type
), mFrequency(frequency
)
77 , mFrameSize(framesize
), mLoopPts
{loopstart
,loopend
}, mStart(start
), mEnd(end
)
79 ~WaveDecoder() override final
;
81 ALuint
getFrequency() const override final
;
82 ChannelConfig
getChannelConfig() const override final
;
83 SampleType
getSampleType() const override final
;
85 uint64_t getLength() const override final
;
86 bool seek(uint64_t pos
) override final
;
88 std::pair
<uint64_t,uint64_t> getLoopPoints() const override final
;
90 ALuint
read(ALvoid
*ptr
, ALuint count
) override final
;
93 WaveDecoder::~WaveDecoder()
98 ALuint
WaveDecoder::getFrequency() const
103 ChannelConfig
WaveDecoder::getChannelConfig() const
105 return mChannelConfig
;
108 SampleType
WaveDecoder::getSampleType() const
114 uint64_t WaveDecoder::getLength() const
116 return (mEnd
- mStart
) / mFrameSize
;
119 bool WaveDecoder::seek(uint64_t pos
)
121 std::streamsize offset
= pos
*mFrameSize
+ mStart
;
123 if(offset
> mEnd
|| !mFile
->seekg(offset
))
128 std::pair
<uint64_t,uint64_t> WaveDecoder::getLoopPoints() const
133 ALuint
WaveDecoder::read(ALvoid
*ptr
, ALuint count
)
137 auto pos
= mFile
->tellg();
138 size_t len
= count
* mFrameSize
;
143 len
= std::min
<std::istream::pos_type
>(len
, mEnd
-pos
);
144 #ifdef __BIG_ENDIAN__
147 case SampleType::Float32
:
148 while(total
< len
&& mFile
->good() && !mFile
->eof())
151 size_t todo
= std::min(len
-total
, sizeof(temp
));
153 mFile
->read(temp
, todo
);
154 std::streamsize got
= mFile
->gcount();
156 for(std::streamsize i
= 0;i
< got
;++i
)
157 reinterpret_cast<char*>(ptr
)[total
+i
] = temp
[i
^3];
164 case SampleType::Int16
:
165 while(total
< len
&& mFile
->good() && !mFile
->eof())
168 size_t todo
= std::min(len
-total
, sizeof(temp
));
170 mFile
->read(temp
, todo
);
171 std::streamsize got
= mFile
->gcount();
173 for(std::streamsize i
= 0;i
< got
;++i
)
174 reinterpret_cast<char*>(ptr
)[total
+i
] = temp
[i
^1];
181 case SampleType::UInt8
:
182 case SampleType::Mulaw
:
186 mFile
->read(reinterpret_cast<char*>(ptr
), len
);
187 total
= mFile
->gcount() / mFrameSize
;
195 SharedPtr
<Decoder
> WaveDecoderFactory::createDecoder(UniquePtr
<std::istream
> &file
)
197 ChannelConfig channels
= ChannelConfig::Mono
;
198 SampleType type
= SampleType::UInt8
;
199 ALuint frequency
= 0;
200 ALuint framesize
= 0;
201 ALuint loop_pts
[2]{0, 0};
202 ALuint blockalign
= 0;
203 ALuint framealign
= 0;
206 if(!file
->read(tag
, 4) || file
->gcount() != 4 || memcmp(tag
, "RIFF", 4) != 0)
208 ALuint totalsize
= read_le32(*file
) & ~1u;
209 if(!file
->read(tag
, 4) || file
->gcount() != 4 || memcmp(tag
, "WAVE", 4) != 0)
212 while(file
->good() && !file
->eof() && totalsize
> 8)
214 if(!file
->read(tag
, 4) || file
->gcount() != 4)
216 ALuint size
= read_le32(*file
);
217 if(size
< 2) return nullptr;
220 size
= std::min((size
+1) & ~1u, totalsize
);
223 if(memcmp(tag
, "fmt ", 4) == 0)
225 /* 'fmt ' tag needs at least 16 bytes. */
226 if(size
< 16) goto next_chunk
;
229 ALushort fmttype
= read_le16(*file
); size
-= 2;
231 /* mono or stereo data */
232 int chancount
= read_le16(*file
); size
-= 2;
234 /* sample frequency */
235 frequency
= read_le32(*file
); size
-= 4;
237 /* skip average bytes per second */
238 read_le32(*file
); size
-= 4;
240 /* bytes per block */
241 blockalign
= read_le16(*file
); size
-= 2;
243 /* bits per sample */
244 int bitdepth
= read_le16(*file
); size
-= 2;
246 /* Look for any extra data and try to find the format */
247 ALuint extrabytes
= 0;
250 extrabytes
= read_le16(*file
);
253 extrabytes
= std::min
<ALuint
>(extrabytes
, size
);
255 /* Format type should be 0x0001 for integer PCM data, 0x0003 for
256 * float PCM data, 0x0007 for muLaw, and 0xFFFE extensible data.
258 if(fmttype
== 0x0001)
261 channels
= ChannelConfig::Mono
;
262 else if(chancount
== 2)
263 channels
= ChannelConfig::Stereo
;
268 type
= SampleType::UInt8
;
269 else if(bitdepth
== 16)
270 type
= SampleType::Int16
;
274 else if(fmttype
== 0x0003)
277 channels
= ChannelConfig::Mono
;
278 else if(chancount
== 2)
279 channels
= ChannelConfig::Stereo
;
284 type
= SampleType::Float32
;
288 else if(fmttype
== 0x0007)
291 channels
= ChannelConfig::Mono
;
292 else if(chancount
== 2)
293 channels
= ChannelConfig::Stereo
;
298 type
= SampleType::Mulaw
;
302 else if(fmttype
== 0xFFFE)
308 ALushort validbits
= read_le16(*file
); size
-= 2;
309 ALuint chanmask
= read_le32(*file
); size
-= 4;
310 file
->read(subtype
, 16); size
-= file
->gcount();
312 /* Padded bit depths not supported */
313 if(validbits
!= bitdepth
)
316 if(memcmp(subtype
, SUBTYPE_BFORMAT_PCM
, 16) == 0 || memcmp(subtype
, SUBTYPE_BFORMAT_FLOAT
, 16) == 0)
322 channels
= ChannelConfig::BFormat2D
;
323 else if(chancount
== 4)
324 channels
= ChannelConfig::BFormat3D
;
328 else if(memcmp(subtype
, SUBTYPE_PCM
, 16) == 0 || memcmp(subtype
, SUBTYPE_FLOAT
, 16) == 0)
330 if(chancount
== 1 && chanmask
== CHANNELS_MONO
)
331 channels
= ChannelConfig::Mono
;
332 else if(chancount
== 2 && chanmask
== CHANNELS_STEREO
)
333 channels
= ChannelConfig::Stereo
;
334 else if(chancount
== 4 && chanmask
== CHANNELS_QUAD
)
335 channels
= ChannelConfig::Quad
;
336 else if(chancount
== 6 && (chanmask
== CHANNELS_5DOT1
|| chanmask
== CHANNELS_5DOT1_REAR
))
337 channels
= ChannelConfig::X51
;
338 else if(chancount
== 7 && chanmask
== CHANNELS_6DOT1
)
339 channels
= ChannelConfig::X61
;
340 else if(chancount
== 8 && chanmask
== CHANNELS_7DOT1
)
341 channels
= ChannelConfig::X71
;
346 if(memcmp(subtype
, SUBTYPE_PCM
, 16) == 0 || memcmp(subtype
, SUBTYPE_BFORMAT_PCM
, 16) == 0)
349 type
= SampleType::UInt8
;
350 else if(bitdepth
== 16)
351 type
= SampleType::Int16
;
355 else if(memcmp(subtype
, SUBTYPE_FLOAT
, 16) == 0 || memcmp(subtype
, SUBTYPE_BFORMAT_FLOAT
, 16) == 0)
358 type
= SampleType::Float32
;
368 framesize
= FramesToBytes(1, channels
, type
);
370 /* Calculate the number of frames per block (ADPCM will need extra
372 framealign
= blockalign
/ framesize
;
374 else if(memcmp(tag
, "smpl", 4) == 0)
376 /* sampler data needs at least 36 bytes */
377 if(size
< 36) goto next_chunk
;
379 /* Most of this only affects MIDI sampling, but we only care about
380 * the loop definitions at the end. */
381 /*ALuint manufacturer =*/ read_le32(*file
);
382 /*ALuint product =*/ read_le32(*file
);
383 /*ALuint smpperiod =*/ read_le32(*file
);
384 /*ALuint unitynote =*/ read_le32(*file
);
385 /*ALuint pitchfrac =*/ read_le32(*file
);
386 /*ALuint smptefmt =*/ read_le32(*file
);
387 /*ALuint smpteoffset =*/ read_le32(*file
);
388 ALuint loopcount
= read_le32(*file
);
389 /*ALuint extrabytes =*/ read_le32(*file
);
392 for(ALuint i
= 0;i
< loopcount
&& size
>= 24;++i
)
394 /*ALuint id =*/ read_le32(*file
);
395 ALuint type
= read_le32(*file
);
396 ALuint loopstart
= read_le32(*file
);
397 ALuint loopend
= read_le32(*file
);
398 /*ALuint frac =*/ read_le32(*file
);
399 ALuint numloops
= read_le32(*file
);
402 /* Only handle indefinite forward loops. */
403 if(type
== 0 || numloops
== 0)
405 loop_pts
[0] = loopstart
;
406 loop_pts
[1] = loopend
;
411 else if(memcmp(tag
, "data", 4) == 0)
413 if(framesize
== 0 || !Context::GetCurrent().isSupported(channels
, type
))
416 /* Make sure there's at least one sample frame of audio data. */
417 std::istream::pos_type start
= file
->tellg();
418 std::istream::pos_type end
= start
+ std::istream::pos_type(size
- (size
%framesize
));
419 if(end
-start
>= framesize
)
421 /* Loop points are byte offsets relative to the data start.
422 * Convert to sample frame offsets. */
423 return MakeShared
<WaveDecoder
>(std::move(file
),
424 channels
, type
, frequency
, framesize
, start
, end
,
425 loop_pts
[0] / blockalign
* framealign
,
426 loop_pts
[1] / blockalign
* framealign