2 * ALURE OpenAL utility library
3 * Copyright (c) 2009-2010 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
40 static inline ALuint
read_le32(std::istream
*file
)
43 if(!file
->read(reinterpret_cast<char*>(buffer
), 4)) return 0;
44 return buffer
[0] | (buffer
[1]<<8) | (buffer
[2]<<16) | (buffer
[3]<<24);
47 static inline ALushort
read_le16(std::istream
*file
)
50 if(!file
->read(reinterpret_cast<char*>(buffer
), 2)) return 0;
51 return buffer
[0] | (buffer
[1]<<8);
54 static inline ALuint
read_be32(std::istream
*file
)
57 if(!file
->read(reinterpret_cast<char*>(buffer
), 4)) return 0;
58 return (buffer
[0]<<24) | (buffer
[1]<<16) | (buffer
[2]<<8) | buffer
[3];
61 static inline ALushort
read_be16(std::istream
*file
)
64 if(!file
->read(reinterpret_cast<char*>(buffer
), 2)) return 0;
65 return (buffer
[0]<<8) | buffer
[1];
68 static inline ALuint
read_be80extended(std::istream
*file
)
71 if(!file
->read(reinterpret_cast<char*>(buffer
), 10)) return 0;
72 ALuint mantissa
, last
= 0;
73 ALubyte exp
= buffer
[1];
75 mantissa
= (buffer
[2]<<24) | (buffer
[3]<<16) | (buffer
[4]<<8) | buffer
[5];
81 if((last
&1)) mantissa
++;
86 struct nullStream
: public alureStream
{
87 virtual bool IsValid() { return false; }
88 virtual bool GetFormat(ALenum
*,ALuint
*,ALuint
*) { return false; }
89 virtual ALuint
GetData(ALubyte
*,ALuint
) { return 0; }
90 virtual bool Rewind() { return false; }
91 nullStream():alureStream(NULL
) {}
95 struct customStream
: public alureStream
{
104 virtual bool IsValid()
105 { return usrFile
!= NULL
; }
107 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
109 if(format
== AL_NONE
)
111 if(!cb
.get_fmt
|| !cb
.get_fmt(usrFile
, &format
, &samplerate
, &blockAlign
))
114 if(DetectBlockAlignment(format
) != blockAlign
)
119 *frequency
= samplerate
;
120 *blockalign
= blockAlign
;
124 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
125 { return cb
.decode(usrFile
, data
, bytes
); }
127 virtual bool Rewind()
129 if(cb
.rewind
&& cb
.rewind(usrFile
))
131 SetError("Rewind failed");
135 customStream(const char *fname
, const UserCallbacks
&callbacks
)
136 : alureStream(NULL
), usrFile(NULL
), format(0), samplerate(0),
137 blockAlign(0), cb(callbacks
)
138 { if(cb
.open_file
) usrFile
= cb
.open_file(fname
); }
140 customStream(const MemDataInfo
&memData
, const UserCallbacks
&callbacks
)
141 : alureStream(NULL
), usrFile(NULL
), format(0), samplerate(0),
142 blockAlign(0), memInfo(memData
), cb(callbacks
)
143 { if(cb
.open_mem
) usrFile
= cb
.open_mem(memInfo
.Data
, memInfo
.Length
); }
145 customStream(void *userdata
, ALenum fmt
, ALuint srate
, const UserCallbacks
&callbacks
)
146 : alureStream(NULL
), usrFile(userdata
), format(fmt
), samplerate(srate
),
147 blockAlign(DetectBlockAlignment(format
)), cb(callbacks
)
150 virtual ~customStream()
152 if(cb
.close
&& usrFile
)
159 struct wavStream
: public alureStream
{
168 virtual bool IsValid()
169 { return (dataStart
> 0 && format
!= AL_NONE
); }
171 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
174 *frequency
= samplerate
;
175 *blockalign
= blockAlign
;
179 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
181 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
182 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
184 std::streamsize got
= fstream
->gcount();
185 got
-= got
%blockAlign
;
188 if(BigEndian
&& sampleSize
== 16)
190 for(std::streamsize i
= 0;i
< got
;i
+=2)
191 swap(data
[i
], data
[i
+1]);
193 else if(BigEndian
&& sampleSize
== 32)
195 for(std::streamsize i
= 0;i
< got
;i
+=4)
197 swap(data
[i
+0], data
[i
+3]);
198 swap(data
[i
+1], data
[i
+2]);
201 else if(BigEndian
&& sampleSize
== 64)
203 for(std::streamsize i
= 0;i
< got
;i
+=8)
205 swap(data
[i
+0], data
[i
+7]);
206 swap(data
[i
+1], data
[i
+6]);
207 swap(data
[i
+2], data
[i
+5]);
208 swap(data
[i
+3], data
[i
+4]);
215 virtual bool Rewind()
218 if(fstream
->seekg(dataStart
))
224 SetError("Seek failed");
228 wavStream(std::istream
*_fstream
)
229 : alureStream(_fstream
), format(0), dataStart(0)
234 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
235 memcmp(buffer
, "RIFF", 4) != 0 || memcmp(buffer
+8, "WAVE", 4) != 0)
238 while(!dataStart
|| format
== AL_NONE
)
241 if(!fstream
->read(tag
, 4))
244 /* read chunk length */
245 length
= read_le32(fstream
);
247 if(memcmp(tag
, "fmt ", 4) == 0 && length
>= 16)
249 /* Data type (should be 1 for PCM data, 3 for float PCM data,
250 * and 17 for IMA4 data) */
251 int type
= read_le16(fstream
);
252 if(type
!= 0x0001 && type
!= 0x0003 && type
!= 0x0011)
255 /* mono or stereo data */
256 int channels
= read_le16(fstream
);
258 /* sample frequency */
259 samplerate
= read_le32(fstream
);
261 /* skip average bytes per second */
264 /* bytes per block */
265 blockAlign
= read_le16(fstream
);
269 /* bits per sample */
270 sampleSize
= read_le16(fstream
);
274 /* Look for any extra data and try to find the format */
278 extrabytes
= read_le16(fstream
);
281 extrabytes
= std::min(extrabytes
, length
);
284 format
= GetSampleFormat(channels
, sampleSize
, false);
285 else if(type
== 0x0003)
286 format
= GetSampleFormat(channels
, sampleSize
, true);
287 else if(type
== 0x0011 && extrabytes
>= 2)
289 int samples
= read_le16(fstream
);
292 /* AL_EXT_IMA4 only supports 36 bytes-per-channel block
293 * alignment, which has 65 uncompressed sample frames */
294 if(blockAlign
== 36*channels
&& samples
== 65*channels
&&
295 alIsExtensionPresent("AL_EXT_IMA4"))
298 format
= AL_FORMAT_MONO_IMA4
;
299 else if(channels
== 2)
300 format
= AL_FORMAT_STEREO_IMA4
;
304 else if(memcmp(tag
, "data", 4) == 0)
306 dataStart
= fstream
->tellg();
307 dataLen
= remLen
= length
;
310 fstream
->seekg(length
, std::ios_base::cur
);
313 if(dataStart
> 0 && format
!= AL_NONE
)
314 fstream
->seekg(dataStart
);
321 struct aiffStream
: public alureStream
{
330 virtual bool IsValid()
331 { return (dataStart
> 0 && format
!= AL_NONE
); }
333 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
336 *frequency
= samplerate
;
337 *blockalign
= blockAlign
;
341 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
343 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
344 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
346 std::streamsize got
= fstream
->gcount();
347 got
-= got
%blockAlign
;
354 for(std::streamsize i
= 0;i
< got
;i
+=2)
355 swap(data
[i
], data
[i
+1]);
357 else if(sampleSize
== 4)
359 for(std::streamsize i
= 0;i
< got
;i
+=4)
361 swap(data
[i
+0], data
[i
+3]);
362 swap(data
[i
+1], data
[i
+2]);
370 virtual bool Rewind()
373 if(fstream
->seekg(dataStart
))
379 SetError("Seek failed");
383 aiffStream(std::istream
*_fstream
)
384 : alureStream(_fstream
), format(0), dataStart(0)
389 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
390 memcmp(buffer
, "FORM", 4) != 0 || memcmp(buffer
+8, "AIFF", 4) != 0)
393 while(!dataStart
|| format
== AL_NONE
)
396 if(!fstream
->read(tag
, 4))
399 /* read chunk length */
400 length
= read_be32(fstream
);
402 if(memcmp(tag
, "COMM", 4) == 0 && length
>= 18)
404 /* mono or stereo data */
405 int channels
= read_be16(fstream
);
407 /* number of sample frames */
410 /* bits per sample */
411 sampleSize
= read_be16(fstream
) / 8;
413 /* sample frequency */
414 samplerate
= read_be80extended(fstream
);
416 /* block alignment */
417 blockAlign
= channels
* sampleSize
;
419 format
= GetSampleFormat(channels
, sampleSize
*8, false);
423 else if(memcmp(tag
, "SSND", 4) == 0)
425 dataStart
= fstream
->tellg();
427 dataLen
= remLen
= length
- 8;
430 fstream
->seekg(length
, std::ios_base::cur
);
433 if(dataStart
> 0 && format
!= AL_NONE
)
434 fstream
->seekg(dataStart
);
437 virtual ~aiffStream()
442 struct sndStream
: public alureStream
{
447 virtual bool IsValid()
448 { return sndFile
!= NULL
; }
450 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
452 if(format
== AL_NONE
)
453 format
= GetSampleFormat(sndInfo
.channels
, 16, false);
455 *frequency
= sndInfo
.samplerate
;
456 *blockalign
= sndInfo
.channels
*2;
460 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
462 const ALuint frameSize
= 2*sndInfo
.channels
;
463 return psf_readf_short(sndFile
, (short*)data
, bytes
/frameSize
) * frameSize
;
466 virtual bool Rewind()
468 if(psf_seek(sndFile
, 0, SEEK_SET
) != -1)
471 SetError("Seek failed");
475 sndStream(std::istream
*_fstream
)
476 : alureStream(_fstream
), sndFile(NULL
), format(AL_NONE
)
478 memset(&sndInfo
, 0, sizeof(sndInfo
));
480 if(!sndfile_handle
) return;
482 static SF_VIRTUAL_IO streamIO
= {
486 sndFile
= psf_open_virtual(&streamIO
, SFM_READ
, &sndInfo
, this);
497 // libSndFile iostream callbacks
498 static sf_count_t
get_filelen(void *user_data
)
500 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
503 std::streampos len
= -1;
504 std::streampos pos
= stream
->tellg();
505 if(stream
->seekg(0, std::ios_base::end
))
507 len
= stream
->tellg();
514 static sf_count_t
seek(sf_count_t offset
, int whence
, void *user_data
)
516 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
519 if(whence
== SEEK_CUR
)
520 stream
->seekg(offset
, std::ios_base::cur
);
521 else if(whence
== SEEK_SET
)
522 stream
->seekg(offset
, std::ios_base::beg
);
523 else if(whence
== SEEK_END
)
524 stream
->seekg(offset
, std::ios_base::end
);
528 return stream
->tellg();
531 static sf_count_t
read(void *ptr
, sf_count_t count
, void *user_data
)
533 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
535 stream
->read(static_cast<char*>(ptr
), count
);
536 return stream
->gcount();
539 static sf_count_t
write(const void*, sf_count_t
, void*)
542 static sf_count_t
tell(void *user_data
)
544 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
546 return stream
->tellg();
550 struct sndStream
: public nullStream
{
551 sndStream(std::istream
*){}
555 #ifdef HAS_VORBISFILE
556 struct oggStream
: public alureStream
{
557 OggVorbis_File oggFile
;
558 vorbis_info
*oggInfo
;
562 virtual bool IsValid()
563 { return oggInfo
!= NULL
; }
565 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
567 if(format
== AL_NONE
)
568 format
= GetSampleFormat(oggInfo
->channels
, 16, false);
570 *frequency
= oggInfo
->rate
;
571 *blockalign
= oggInfo
->channels
*2;
575 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
580 int res
= pov_read(&oggFile
, (char*)&data
[got
], bytes
, BigEndian
?1:0, 2, 1, &oggBitstream
);
586 // 1, 2, and 4 channel files decode into the same channel order as
587 // OpenAL, however 6(5.1), 7(6.1), and 8(7.1) channel files need to be
589 if(oggInfo
->channels
== 6)
591 ALshort
*samples
= (ALshort
*)data
;
592 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=6)
594 // OpenAL : FL, FR, FC, LFE, RL, RR
595 // Vorbis : FL, FC, FR, RL, RR, LFE
596 swap(samples
[i
+1], samples
[i
+2]);
597 swap(samples
[i
+3], samples
[i
+5]);
598 swap(samples
[i
+4], samples
[i
+5]);
601 else if(oggInfo
->channels
== 7)
603 ALshort
*samples
= (ALshort
*)data
;
604 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=7)
606 // OpenAL : FL, FR, FC, LFE, RC, SL, SR
607 // Vorbis : FL, FC, FR, SL, SR, RC, LFE
608 swap(samples
[i
+1], samples
[i
+2]);
609 swap(samples
[i
+3], samples
[i
+6]);
610 swap(samples
[i
+4], samples
[i
+6]);
611 swap(samples
[i
+5], samples
[i
+6]);
614 else if(oggInfo
->channels
== 8)
616 ALshort
*samples
= (ALshort
*)data
;
617 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=8)
619 // OpenAL : FL, FR, FC, LFE, RL, RR, SL, SR
620 // Vorbis : FL, FC, FR, SL, SR, RL, RR, LFE
621 swap(samples
[i
+1], samples
[i
+2]);
622 swap(samples
[i
+3], samples
[i
+7]);
623 swap(samples
[i
+4], samples
[i
+5]);
624 swap(samples
[i
+5], samples
[i
+6]);
625 swap(samples
[i
+6], samples
[i
+7]);
631 virtual bool Rewind()
633 if(pov_pcm_seek(&oggFile
, 0) == 0)
636 SetError("Seek failed");
640 oggStream(std::istream
*_fstream
)
641 : alureStream(_fstream
), oggInfo(NULL
), oggBitstream(0), format(AL_NONE
)
643 if(!vorbisfile_handle
) return;
645 const ov_callbacks streamIO
= {
646 read
, seek
, close
, tell
649 if(pov_open_callbacks(this, &oggFile
, NULL
, 0, streamIO
) == 0)
651 oggInfo
= pov_info(&oggFile
, -1);
665 // libVorbisFile iostream callbacks
666 static int seek(void *user_data
, ogg_int64_t offset
, int whence
)
668 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
671 if(whence
== SEEK_CUR
)
672 stream
->seekg(offset
, std::ios_base::cur
);
673 else if(whence
== SEEK_SET
)
674 stream
->seekg(offset
, std::ios_base::beg
);
675 else if(whence
== SEEK_END
)
676 stream
->seekg(offset
, std::ios_base::end
);
680 return stream
->tellg();
683 static size_t read(void *ptr
, size_t size
, size_t nmemb
, void *user_data
)
685 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
688 stream
->read(static_cast<char*>(ptr
), nmemb
*size
);
689 size_t ret
= stream
->gcount();
693 static long tell(void *user_data
)
695 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
697 return stream
->tellg();
700 static int close(void*)
706 struct oggStream
: public nullStream
{
707 oggStream(std::istream
*){}
712 struct flacStream
: public alureStream
{
713 FLAC__StreamDecoder
*flacFile
;
719 std::vector
<ALubyte
> initialData
;
725 virtual bool IsValid()
726 { return flacFile
!= NULL
; }
728 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
731 *frequency
= samplerate
;
732 *blockalign
= blockAlign
;
736 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
742 if(initialData
.size() > 0)
744 size_t rem
= std::min(initialData
.size(), (size_t)bytes
);
745 memcpy(data
, &initialData
[0], rem
);
747 initialData
.erase(initialData
.begin(), initialData
.begin()+rem
);
750 while(outTotal
< bytes
)
752 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
753 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
760 virtual bool Rewind()
762 if(pFLAC__stream_decoder_seek_absolute(flacFile
, 0) != false)
768 SetError("Seek failed");
772 flacStream(std::istream
*_fstream
)
773 : alureStream(_fstream
), flacFile(NULL
), format(AL_NONE
), samplerate(0),
774 blockAlign(0), useFloat(AL_FALSE
)
776 if(!flac_handle
) return;
778 flacFile
= pFLAC__stream_decoder_new();
781 if(pFLAC__stream_decoder_init_stream(flacFile
, ReadCallback
, SeekCallback
, TellCallback
, LengthCallback
, EofCallback
, WriteCallback
, MetadataCallback
, ErrorCallback
, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK
)
789 pFLAC__stream_decoder_finish(flacFile
);
791 pFLAC__stream_decoder_delete(flacFile
);
796 virtual ~flacStream()
800 pFLAC__stream_decoder_finish(flacFile
);
801 pFLAC__stream_decoder_delete(flacFile
);
809 // We need to decode some data to be able to get the channel count, bit
810 // depth, and sample rate. It also ensures the file has FLAC data, as
811 // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
815 while(initialData
.size() == 0)
817 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
818 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
822 if(initialData
.size() > 0)
827 static FLAC__StreamDecoderWriteStatus
WriteCallback(const FLAC__StreamDecoder
*, const FLAC__Frame
*frame
, const FLAC__int32
*const buffer
[], void *client_data
)
829 flacStream
*self
= static_cast<flacStream
*>(client_data
);
830 ALubyte
*data
= self
->outBytes
+ self
->outTotal
;
833 if(self
->format
== AL_NONE
)
835 ALuint bps
= frame
->header
.bits_per_sample
;
836 if(bps
== 24 || bps
== 32)
838 self
->format
= GetSampleFormat(frame
->header
.channels
, 32, true);
839 if(self
->format
!= AL_NONE
)
841 self
->useFloat
= AL_TRUE
;
846 if(self
->format
== AL_NONE
)
847 self
->format
= GetSampleFormat(frame
->header
.channels
, bps
, false);
848 self
->blockAlign
= frame
->header
.channels
* bps
/8;
849 self
->samplerate
= frame
->header
.sample_rate
;
852 const ALboolean useFloat
= self
->useFloat
;
853 while(self
->outTotal
< self
->outLen
&& i
< frame
->header
.blocksize
)
855 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
857 if(frame
->header
.bits_per_sample
== 8)
858 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
859 else if(frame
->header
.bits_per_sample
== 16)
860 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
861 else if(frame
->header
.bits_per_sample
== 24)
864 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
865 buffer
[c
][i
]/(float)0x7FFFFF :
866 buffer
[c
][i
]/(float)0x800000);
868 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
870 else if(frame
->header
.bits_per_sample
== 32)
873 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
874 buffer
[c
][i
]/(float)0x7FFFFFFF :
875 buffer
[c
][i
]/(float)0x80000000u
);
877 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
880 self
->outTotal
+= self
->blockAlign
;
881 data
+= self
->blockAlign
;
885 if(i
< frame
->header
.blocksize
)
887 ALuint blocklen
= (frame
->header
.blocksize
-i
) *
889 ALuint start
= self
->initialData
.size();
891 self
->initialData
.resize(start
+blocklen
);
892 data
= &self
->initialData
[start
];
895 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
897 if(frame
->header
.bits_per_sample
== 8)
898 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
899 else if(frame
->header
.bits_per_sample
== 16)
900 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
901 else if(frame
->header
.bits_per_sample
== 24)
904 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
905 buffer
[c
][i
]/(float)0x7FFFFF :
906 buffer
[c
][i
]/(float)0x800000);
908 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
910 else if(frame
->header
.bits_per_sample
== 32)
913 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
914 buffer
[c
][i
]/(float)0x7FFFFFFF :
915 buffer
[c
][i
]/(float)0x80000000u
);
917 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
920 data
+= self
->blockAlign
;
922 } while(i
< frame
->header
.blocksize
);
925 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
927 static void MetadataCallback(const FLAC__StreamDecoder
*,const FLAC__StreamMetadata
*,void*)
930 static void ErrorCallback(const FLAC__StreamDecoder
*,FLAC__StreamDecoderErrorStatus
,void*)
934 static FLAC__StreamDecoderReadStatus
ReadCallback(const FLAC__StreamDecoder
*, FLAC__byte buffer
[], size_t *bytes
, void *client_data
)
936 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
940 return FLAC__STREAM_DECODER_READ_STATUS_ABORT
;
942 stream
->read(reinterpret_cast<char*>(buffer
), *bytes
);
943 *bytes
= stream
->gcount();
944 if(*bytes
== 0 && stream
->eof())
945 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
;
947 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
;
949 static FLAC__StreamDecoderSeekStatus
SeekCallback(const FLAC__StreamDecoder
*, FLAC__uint64 absolute_byte_offset
, void *client_data
)
951 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
954 if(!stream
->seekg(absolute_byte_offset
))
955 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
;
956 return FLAC__STREAM_DECODER_SEEK_STATUS_OK
;
958 static FLAC__StreamDecoderTellStatus
TellCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*absolute_byte_offset
, void *client_data
)
960 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
963 *absolute_byte_offset
= stream
->tellg();
964 return FLAC__STREAM_DECODER_TELL_STATUS_OK
;
966 static FLAC__StreamDecoderLengthStatus
LengthCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*stream_length
, void *client_data
)
968 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
971 std::streampos pos
= stream
->tellg();
972 if(stream
->seekg(0, std::ios_base::end
))
974 *stream_length
= stream
->tellg();
979 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
;
980 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK
;
982 static FLAC__bool
EofCallback(const FLAC__StreamDecoder
*, void *client_data
)
984 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
985 return (stream
->eof()) ? true : false;
989 struct flacStream
: public nullStream
{
990 flacStream(std::istream
*){}
996 struct mp3Stream
: public alureStream
{
997 mpg123_handle
*mp3File
;
1002 virtual bool IsValid()
1003 { return mp3File
!= NULL
; }
1005 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1008 *frequency
= samplerate
;
1009 *blockalign
= channels
*2;
1013 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1019 int ret
= pmpg123_read(mp3File
, data
, bytes
, &got
);
1025 if(ret
== MPG123_NEW_FORMAT
)
1029 pmpg123_getformat(mp3File
, &newrate
, &newchans
, &enc
);
1032 if(ret
== MPG123_NEED_MORE
)
1034 unsigned char data
[4096];
1035 fstream
->read((char*)data
, sizeof(data
));
1036 std::streamsize insize
= fstream
->gcount();
1037 if(insize
> 0 && pmpg123_feed(mp3File
, data
, insize
) == MPG123_OK
)
1046 virtual bool Rewind()
1049 std::istream::pos_type oldpos
= fstream
->tellg();
1052 mpg123_handle
*newFile
= pmpg123_new(NULL
, NULL
);
1053 if(pmpg123_open_feed(newFile
) == MPG123_OK
)
1055 unsigned char data
[4096];
1060 ALuint amt
, total
= 0;
1061 int ret
= MPG123_OK
;
1063 fstream
->read((char*)data
, sizeof(data
));
1064 amt
= fstream
->gcount();
1067 ret
= pmpg123_decode(newFile
, data
, amt
, NULL
, 0, NULL
);
1068 } while(ret
== MPG123_NEED_MORE
&& total
< 64*1024);
1070 if(ret
== MPG123_NEW_FORMAT
&&
1071 pmpg123_getformat(newFile
, &newrate
, &newchans
, &enc
) == MPG123_OK
)
1073 if(pmpg123_format_none(newFile
) == MPG123_OK
&&
1074 pmpg123_format(newFile
, samplerate
, channels
, MPG123_ENC_SIGNED_16
) == MPG123_OK
)
1077 pmpg123_delete(mp3File
);
1082 pmpg123_delete(newFile
);
1085 fstream
->seekg(oldpos
);
1086 SetError("Restart failed");
1090 mp3Stream(std::istream
*_fstream
)
1091 : alureStream(_fstream
), mp3File(NULL
), format(AL_NONE
)
1093 if(!mp123_handle
) return;
1095 mp3File
= pmpg123_new(NULL
, NULL
);
1096 if(pmpg123_open_feed(mp3File
) == MPG123_OK
)
1098 unsigned char data
[4096];
1101 ALuint amt
, total
= 0;
1102 int ret
= MPG123_OK
;
1104 fstream
->read((char*)data
, sizeof(data
));
1105 amt
= fstream
->gcount();
1108 ret
= pmpg123_decode(mp3File
, data
, amt
, NULL
, 0, NULL
);
1109 } while(ret
== MPG123_NEED_MORE
&& total
< 64*1024);
1111 if(ret
== MPG123_NEW_FORMAT
&&
1112 pmpg123_getformat(mp3File
, &samplerate
, &channels
, &enc
) == MPG123_OK
)
1114 format
= GetSampleFormat(channels
, 16, false);
1115 if(pmpg123_format_none(mp3File
) == MPG123_OK
&&
1116 pmpg123_format(mp3File
, samplerate
, channels
, MPG123_ENC_SIGNED_16
) == MPG123_OK
)
1123 pmpg123_delete(mp3File
);
1127 virtual ~mp3Stream()
1130 pmpg123_delete(mp3File
);
1135 struct mp3Stream
: public nullStream
{
1136 mp3Stream(std::istream
*){}
1142 struct dumbStream
: public alureStream
{
1143 DUMBFILE_SYSTEM vfs
;
1146 DUH_SIGRENDERER
*renderer
;
1147 std::vector
<sample_t
> sampleBuf
;
1152 virtual bool IsValid()
1153 { return renderer
!= NULL
; }
1155 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1157 if(format
== AL_NONE
)
1159 format
= GetSampleFormat(2, 32, true);
1160 if(format
== AL_NONE
)
1161 format
= AL_FORMAT_STEREO16
;
1164 *frequency
= samplerate
;
1165 *blockalign
= 2 * ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) :
1170 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1174 if(pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(renderer
)) == 0)
1177 ALuint sample_count
= bytes
/ ((format
==AL_FORMAT_STEREO16
) ?
1178 sizeof(ALshort
) : sizeof(ALfloat
));
1180 sampleBuf
.resize(sample_count
);
1181 sample_t
*samples
[] = {
1185 pdumb_silence(samples
[0], sample_count
);
1186 ret
= pduh_sigrenderer_generate_samples(renderer
, 1.0f
, 65536.0f
/samplerate
, sample_count
/2, samples
);
1188 if(format
== AL_FORMAT_STEREO16
)
1190 for(ALuint i
= 0;i
< ret
;i
++)
1191 ((ALshort
*)data
)[i
] = clamp(samples
[0][i
]>>8, -32768, 32767);
1195 for(ALuint i
= 0;i
< ret
;i
++)
1196 ((ALfloat
*)data
)[i
] = ((samples
[0][i
]>=0) ?
1197 samples
[0][i
]/(float)0x7FFFFF :
1198 samples
[0][i
]/(float)0x800000);
1200 ret
*= ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) : sizeof(ALfloat
));
1205 virtual bool Rewind()
1207 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
1210 SetError("Could start renderer");
1213 pduh_end_sigrenderer(renderer
);
1214 renderer
= newrenderer
;
1218 virtual bool SetOrder(ALuint order
)
1220 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, order
);
1223 SetError("Could not set order");
1226 pduh_end_sigrenderer(renderer
);
1227 renderer
= newrenderer
;
1233 dumbStream(std::istream
*_fstream
)
1234 : alureStream(_fstream
), dumbFile(NULL
), duh(NULL
), renderer(NULL
),
1235 lastOrder(0), format(AL_NONE
), samplerate(48000)
1237 if(!dumb_handle
) return;
1239 ALCdevice
*device
= alcGetContextsDevice(alcGetCurrentContext());
1241 alcGetIntegerv(device
, ALC_FREQUENCY
, 1, &samplerate
);
1243 DUH
* (*funcs
[])(DUMBFILE
*) = {
1253 vfs
.getc
= read_char
;
1257 for(size_t i
= 0;funcs
[i
];i
++)
1259 dumbFile
= pdumbfile_open_ex(this, &vfs
);
1262 duh
= funcs
[i
](dumbFile
);
1265 renderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
1268 pdumb_it_set_loop_callback(pduh_get_it_sigrenderer(renderer
), loop_cb
, this);
1276 pdumbfile_close(dumbFile
);
1284 virtual ~dumbStream()
1287 pduh_end_sigrenderer(renderer
);
1295 pdumbfile_close(dumbFile
);
1300 // DUMBFILE iostream callbacks
1301 static int skip(void *user_data
, long offset
)
1303 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1306 if(stream
->seekg(offset
, std::ios_base::cur
))
1311 static long read(char *ptr
, long size
, void *user_data
)
1313 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1316 stream
->read(ptr
, size
);
1317 return stream
->gcount();
1320 static int read_char(void *user_data
)
1322 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1326 stream
->read(reinterpret_cast<char*>(&ret
), 1);
1327 if(stream
->gcount() > 0)
1332 static int loop_cb(void *user_data
)
1334 dumbStream
*self
= static_cast<dumbStream
*>(user_data
);
1335 pdumb_it_sr_set_speed(pduh_get_it_sigrenderer(self
->renderer
), 0);
1340 struct dumbStream
: public nullStream
{
1341 dumbStream(std::istream
*){}
1346 #ifdef HAS_FLUIDSYNTH
1347 struct fluidStream
: public alureStream
{
1349 static const ALubyte MIDI_CHANNEL_MASK
= 0x0F;
1350 static const ALubyte MIDI_EVENT_MASK
= 0xF0;
1352 static const ALubyte MIDI_NOTEOFF
= 0x80; // + note + velocity
1353 static const ALubyte MIDI_NOTEON
= 0x90; // + note + velocity
1354 static const ALubyte MIDI_POLYPRESS
= 0xA0; // + pressure (2 bytes)
1355 static const ALubyte MIDI_CTRLCHANGE
= 0xB0; // + ctrl + value
1356 static const ALubyte MIDI_PRGMCHANGE
= 0xC0; // + new patch
1357 static const ALubyte MIDI_CHANPRESS
= 0xD0; // + pressure (1 byte)
1358 static const ALubyte MIDI_PITCHBEND
= 0xE0; // + pitch bend (2 bytes)
1359 static const ALubyte MIDI_SPECIAL
= 0xF0; // Special event
1361 static const ALubyte MIDI_SYSEX
= 0xF0; // SysEx begin
1362 static const ALubyte MIDI_SYSEXEND
= 0xF7; // SysEx end
1363 static const ALubyte MIDI_SONGPOS
= 0xF2; // Song position
1364 static const ALubyte MIDI_SONGSEL
= 0xF3; // Song select
1365 static const ALubyte MIDI_META
= 0xFF; // Meta event begin
1367 static const ALubyte MIDI_META_EOT
= 0x2F; // End-of-track
1368 static const ALubyte MIDI_META_TEMPO
= 0x51; // Tempo change
1371 std::vector
<ALubyte
> data
;
1374 ALdouble SamplesLeft
;
1376 MidiTrack() : Offset(0), LastEvent(0), SamplesLeft(0.)
1385 MidiTrack
& operator=(const MidiTrack
&rhs
)
1388 Offset
= rhs
.Offset
;
1389 LastEvent
= rhs
.LastEvent
;
1390 SamplesLeft
= rhs
.SamplesLeft
;
1394 unsigned long ReadVarLen()
1396 if(Offset
>= data
.size())
1399 unsigned long len
= data
[Offset
]&0x7F;
1400 while((data
[Offset
]&0x80))
1402 if(++Offset
>= data
.size())
1404 len
= (len
<<7) | (data
[Offset
]&0x7F);
1413 std::vector
<MidiTrack
> Tracks
;
1417 ALdouble samplesPerTick
;
1419 fluid_settings_t
*fluidSettings
;
1420 fluid_synth_t
*fluidSynth
;
1424 virtual bool IsValid()
1425 { return fluidSynth
!= NULL
; }
1427 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1429 if(format
== AL_NONE
)
1431 format
= GetSampleFormat(2, 32, true);
1432 if(format
== AL_NONE
)
1433 format
= AL_FORMAT_STEREO16
;
1436 *frequency
= sampleRate
;
1437 *blockalign
= 2 * ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) :
1442 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1446 if(format
== AL_FORMAT_STEREO16
)
1448 ALshort
*ptr
= reinterpret_cast<ALshort
*>(data
);
1449 ret
= FillBuffer(ptr
, bytes
/2/sizeof(ALshort
));
1450 ret
*= 2 * sizeof(ALshort
);
1454 ALfloat
*ptr
= reinterpret_cast<ALfloat
*>(data
);
1455 ret
= FillBuffer(ptr
, bytes
/2/sizeof(ALfloat
));
1456 ret
*= 2 * sizeof(ALfloat
);
1462 virtual bool Rewind()
1464 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(), end
= Tracks
.end();i
!= end
;i
++)
1467 unsigned long val
= i
->ReadVarLen();
1468 i
->SamplesLeft
+= val
* samplesPerTick
;
1470 pfluid_synth_program_reset(fluidSynth
);
1471 UpdateTempo(500000);
1475 fluidStream(std::istream
*_fstream
)
1476 : alureStream(_fstream
), Divisions(100),
1477 format(AL_NONE
), sampleRate(48000), samplesPerTick(1.),
1478 fluidSettings(NULL
), fluidSynth(NULL
), fontID(FLUID_FAILED
)
1480 if(!fsynth_handle
) return;
1482 ALCdevice
*device
= alcGetContextsDevice(alcGetCurrentContext());
1484 alcGetIntegerv(device
, ALC_FREQUENCY
, 1, &sampleRate
);
1487 if(!fstream
->read(hdr
, 4))
1490 if(memcmp(hdr
, "MThd", 4) == 0)
1492 ALuint len
= read_be32(fstream
);
1496 int type
= read_be16(fstream
);
1497 if(type
!= 0 && type
!= 1)
1500 ALuint numtracks
= read_be16(fstream
);
1502 Divisions
= read_be16(fstream
);
1503 UpdateTempo(500000);
1505 Tracks
.resize(numtracks
);
1506 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(), end
= Tracks
.end();i
!= end
;i
++)
1508 if(!fstream
->read(hdr
, 4) || memcmp(hdr
, "MTrk", 4) != 0)
1511 ALuint len
= read_be32(fstream
);
1512 i
->data
.resize(len
);
1513 if(!fstream
->read(reinterpret_cast<char*>(&i
->data
[0]), len
))
1516 unsigned long val
= i
->ReadVarLen();
1517 i
->SamplesLeft
+= val
* samplesPerTick
;
1523 virtual ~fluidStream()
1525 if(fontID
!= FLUID_FAILED
)
1526 pfluid_synth_sfunload(fluidSynth
, fontID
, true);
1527 fontID
= FLUID_FAILED
;
1529 if(fluidSynth
!= NULL
)
1530 pdelete_fluid_synth(fluidSynth
);
1533 if(fluidSettings
!= NULL
)
1534 pdelete_fluid_settings(fluidSettings
);
1535 fluidSettings
= NULL
;
1539 template<typename T
>
1540 ALuint
FillBuffer(T
*Buffer
, ALuint BufferSamples
)
1542 ALuint SamplesInBuffer
= 0;
1543 while(SamplesInBuffer
< BufferSamples
)
1545 // Check if any tracks are still playing and how many samples are waiting to render
1546 size_t TracksPlaying
= 0;
1547 ALuint SamplesToDo
= BufferSamples
- SamplesInBuffer
;
1548 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(),
1549 end
= Tracks
.end();i
!= end
;i
++)
1551 if(i
->Offset
< i
->data
.size())
1553 SamplesToDo
= std::min
<ALuint
>(SamplesToDo
, i
->SamplesLeft
);
1557 if(TracksPlaying
== 0)
1560 if(SamplesToDo
== 0)
1567 WriteSamples(SamplesToDo
, Buffer
);
1568 Buffer
+= SamplesToDo
*2;
1569 SamplesInBuffer
+= SamplesToDo
;
1571 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(),
1572 end
= Tracks
.end();i
!= end
;i
++)
1574 if(i
->Offset
< i
->data
.size())
1575 i
->SamplesLeft
-= SamplesToDo
;
1579 return SamplesInBuffer
;
1582 void WriteSamples(ALuint count
, short *buffer
)
1583 { pfluid_synth_write_s16(fluidSynth
, count
, buffer
, 0, 2, buffer
, 1, 2); }
1584 void WriteSamples(ALuint count
, float *buffer
)
1585 { pfluid_synth_write_float(fluidSynth
, count
, buffer
, 0, 2, buffer
, 1, 2); }
1589 ALuint newtempo
= 0;
1591 // Process more events
1592 std::vector
<MidiTrack
>::iterator i
=Tracks
.begin(), end
=Tracks
.end();
1595 if(i
->Offset
>= i
->data
.size() || i
->SamplesLeft
>= 1.)
1601 if(i
->data
.size() - i
->Offset
< 3)
1603 i
->Offset
= i
->data
.size();
1608 ALubyte event
= i
->data
[i
->Offset
++];
1609 ALubyte parm1
, parm2
;
1612 event
= i
->LastEvent
;
1615 if((event
&MIDI_EVENT_MASK
) != MIDI_SPECIAL
)
1616 i
->LastEvent
= event
;
1617 parm1
= i
->data
[i
->Offset
];
1618 parm2
= i
->data
[i
->Offset
+1];
1620 int channel
= event
&MIDI_CHANNEL_MASK
;
1621 switch(event
&MIDI_EVENT_MASK
)
1624 pfluid_synth_noteoff(fluidSynth
, channel
, parm1
);
1628 pfluid_synth_noteon(fluidSynth
, channel
, parm1
, parm2
);
1631 case MIDI_POLYPRESS
:
1635 case MIDI_CTRLCHANGE
:
1636 pfluid_synth_cc(fluidSynth
, channel
, parm1
, parm2
);
1639 case MIDI_PRGMCHANGE
:
1640 pfluid_synth_program_change(fluidSynth
, channel
, parm1
);
1644 case MIDI_CHANPRESS
:
1645 pfluid_synth_channel_pressure(fluidSynth
, channel
, parm1
);
1649 case MIDI_PITCHBEND
:
1650 pfluid_synth_pitch_bend(fluidSynth
, channel
, (parm1
&0x7F) | ((parm2
&0x7F)<<7));
1660 unsigned long len
= i
->ReadVarLen();
1662 if(i
->data
.size() - i
->Offset
< len
)
1664 i
->Offset
= i
->data
.size();
1668 if(len
> 1 && i
->data
[len
-1] == MIDI_SYSEXEND
)
1670 char *data
= reinterpret_cast<char*>(&i
->data
[i
->Offset
]);
1671 pfluid_synth_sysex(fluidSynth
, data
, len
-1, NULL
, NULL
, NULL
, false);
1687 ALubyte metatype
= i
->data
[i
->Offset
++];
1688 unsigned long val
= i
->ReadVarLen();
1690 if(i
->data
.size() - i
->Offset
< val
)
1692 i
->Offset
= i
->data
.size();
1696 if(metatype
== MIDI_META_EOT
)
1698 i
->Offset
= i
->data
.size();
1702 if(metatype
== MIDI_META_TEMPO
&& val
>= 3)
1704 newtempo
= (i
->data
[i
->Offset
] << 16) |
1705 (i
->data
[i
->Offset
+1] << 8) |
1706 (i
->data
[i
->Offset
+2]);
1714 /* The rest of the special events don't have any
1721 /* Shouldn't ever get to here */
1725 unsigned long val
= i
->ReadVarLen();
1726 i
->SamplesLeft
+= val
* samplesPerTick
;
1729 UpdateTempo(newtempo
);
1732 void UpdateTempo(ALuint tempo
)
1734 ALdouble sampletickrate
= sampleRate
/ (1000000. / tempo
) / Divisions
;
1736 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(),
1737 end
= Tracks
.end();i
!= end
;i
++)
1739 if(i
->Offset
>= i
->data
.size())
1741 i
->SamplesLeft
= i
->SamplesLeft
/ samplesPerTick
* sampletickrate
;
1743 samplesPerTick
= sampletickrate
;
1748 fluidSettings
= pnew_fluid_settings();
1751 pfluid_settings_setnum(fluidSettings
, "synth.gain", 0.5);
1752 pfluid_settings_setstr(fluidSettings
, "synth.reverb.active", "yes");
1753 pfluid_settings_setstr(fluidSettings
, "synth.chorus.active", "yes");
1754 pfluid_settings_setint(fluidSettings
, "synth.polyphony", 256);
1755 pfluid_settings_setnum(fluidSettings
, "synth.sample-rate", (double)sampleRate
);
1757 fluidSynth
= pnew_fluid_synth(fluidSettings
);
1760 const char *soundfont
= getenv("FLUID_SOUNDFONT");
1761 if((fontID
=pfluid_synth_sfload(fluidSynth
, soundfont
, true)) == FLUID_FAILED
)
1763 pdelete_fluid_synth(fluidSynth
);
1771 struct fluidStream
: public nullStream
{
1772 fluidStream(std::istream
*){}
1777 template <typename T
>
1778 alureStream
*get_stream_decoder(const T
&fdata
)
1780 alureStream
*stream
;
1782 std::map
<ALint
,UserCallbacks
>::iterator i
= InstalledCallbacks
.begin();
1783 while(i
!= InstalledCallbacks
.end() && i
->first
< 0)
1785 stream
= new customStream(fdata
, i
->second
);
1786 if(stream
->IsValid())
1792 std::istream
*file
= new InStream(fdata
);
1795 stream
= new wavStream(file
);
1796 if(stream
->IsValid())
1801 file
->seekg(0, std::ios_base::beg
);
1802 stream
= new aiffStream(file
);
1803 if(stream
->IsValid())
1807 // Try libVorbisFile
1809 file
->seekg(0, std::ios_base::beg
);
1810 stream
= new oggStream(file
);
1811 if(stream
->IsValid())
1817 file
->seekg(0, std::ios_base::beg
);
1818 stream
= new flacStream(file
);
1819 if(stream
->IsValid())
1825 file
->seekg(0, std::ios_base::beg
);
1826 stream
= new fluidStream(file
);
1827 if(stream
->IsValid())
1833 file
->seekg(0, std::ios_base::beg
);
1834 stream
= new dumbStream(file
);
1835 if(stream
->IsValid())
1841 file
->seekg(0, std::ios_base::beg
);
1842 stream
= new sndStream(file
);
1843 if(stream
->IsValid())
1849 file
->seekg(0, std::ios_base::beg
);
1850 stream
= new mp3Stream(file
);
1851 if(stream
->IsValid())
1855 SetError("Unsupported type");
1860 SetError("Failed to open file");
1864 while(i
!= InstalledCallbacks
.end())
1866 stream
= new customStream(fdata
, i
->second
);
1867 if(stream
->IsValid())
1873 return new nullStream
;
1876 alureStream
*create_stream(const char *fname
)
1877 { return get_stream_decoder(fname
); }
1878 alureStream
*create_stream(const MemDataInfo
&memData
)
1879 { return get_stream_decoder(memData
); }
1881 alureStream
*create_stream(ALvoid
*userdata
, ALenum format
, ALuint rate
, const UserCallbacks
&cb
)
1882 { return new customStream(userdata
, format
, rate
, cb
); }