2 * ALURE OpenAL utility library
3 * Copyright (C) 2009-2010 by Chris Robinson.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
37 static inline ALuint
read_le32(std::istream
*file
)
40 if(!file
->read(reinterpret_cast<char*>(buffer
), 4)) return 0;
41 return buffer
[0] | (buffer
[1]<<8) | (buffer
[2]<<16) | (buffer
[3]<<24);
44 static inline ALushort
read_le16(std::istream
*file
)
47 if(!file
->read(reinterpret_cast<char*>(buffer
), 2)) return 0;
48 return buffer
[0] | (buffer
[1]<<8);
51 static inline ALuint
read_be32(std::istream
*file
)
54 if(!file
->read(reinterpret_cast<char*>(buffer
), 4)) return 0;
55 return (buffer
[0]<<24) | (buffer
[1]<<16) | (buffer
[2]<<8) | buffer
[3];
58 static inline ALushort
read_be16(std::istream
*file
)
61 if(!file
->read(reinterpret_cast<char*>(buffer
), 2)) return 0;
62 return (buffer
[0]<<8) | buffer
[1];
65 static inline ALuint
read_be80extended(std::istream
*file
)
68 if(!file
->read(reinterpret_cast<char*>(buffer
), 10)) return 0;
69 ALuint mantissa
, last
= 0;
70 ALubyte exp
= buffer
[1];
72 mantissa
= (buffer
[2]<<24) | (buffer
[3]<<16) | (buffer
[4]<<8) | buffer
[5];
78 if((last
&1)) mantissa
++;
83 struct nullStream
: public alureStream
{
84 virtual bool IsValid() { return false; }
85 virtual bool GetFormat(ALenum
*,ALuint
*,ALuint
*) { return false; }
86 virtual ALuint
GetData(ALubyte
*,ALuint
) { return 0; }
87 virtual bool Rewind() { return false; }
88 nullStream():alureStream(NULL
) {}
92 struct customStream
: public alureStream
{
101 virtual bool IsValid()
102 { return usrFile
!= NULL
; }
104 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
106 if(format
== AL_NONE
)
109 !cb
.get_fmt(usrFile
, &this->format
, &samplerate
, &blockAlign
))
114 *frequency
= samplerate
;
115 *blockalign
= blockAlign
;
119 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
120 { return cb
.decode(usrFile
, data
, bytes
); }
122 virtual bool Rewind()
124 if(cb
.rewind
&& cb
.rewind(usrFile
))
126 SetError("Rewind failed");
130 customStream(const char *fname
, const UserCallbacks
&callbacks
)
131 : alureStream(NULL
), usrFile(NULL
), format(0), samplerate(0),
132 blockAlign(0), cb(callbacks
)
133 { if(cb
.open_file
) usrFile
= cb
.open_file(fname
); }
135 customStream(const MemDataInfo
&memData
, const UserCallbacks
&callbacks
)
136 : alureStream(NULL
), usrFile(NULL
), format(0), samplerate(0),
137 blockAlign(0), memInfo(memData
), cb(callbacks
)
138 { if(cb
.open_mem
) usrFile
= cb
.open_mem(memInfo
.Data
, memInfo
.Length
); }
140 customStream(void *userdata
, ALenum fmt
, ALuint srate
, const UserCallbacks
&callbacks
)
141 : alureStream(NULL
), usrFile(userdata
), format(fmt
), samplerate(srate
),
142 blockAlign(DetectBlockAlignment(format
)), cb(callbacks
)
145 virtual ~customStream()
147 if(cb
.close
&& usrFile
)
154 struct wavStream
: public alureStream
{
163 virtual bool IsValid()
164 { return (dataStart
> 0 && format
!= AL_NONE
); }
166 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
169 *frequency
= samplerate
;
170 *blockalign
= blockAlign
;
174 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
176 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
177 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
179 std::streamsize got
= fstream
->gcount();
180 got
-= got
%blockAlign
;
183 if(BigEndian
&& sampleSize
> 1)
187 for(std::streamsize i
= 0;i
< got
;i
+=2)
188 swap(data
[i
], data
[i
+1]);
190 else if(sampleSize
== 4)
192 for(std::streamsize i
= 0;i
< got
;i
+=4)
194 swap(data
[i
+0], data
[i
+3]);
195 swap(data
[i
+1], data
[i
+2]);
203 virtual bool Rewind()
206 if(fstream
->seekg(dataStart
))
212 SetError("Seek failed");
216 wavStream(std::istream
*_fstream
)
217 : alureStream(_fstream
), format(0), dataStart(0)
222 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
223 memcmp(buffer
, "RIFF", 4) != 0 || memcmp(buffer
+8, "WAVE", 4) != 0)
226 while(!dataStart
|| format
== AL_NONE
)
229 if(!fstream
->read(tag
, 4))
232 /* read chunk length */
233 length
= read_le32(fstream
);
235 if(memcmp(tag
, "fmt ", 4) == 0 && length
>= 16)
237 /* Data type (should be 1 for PCM data) */
238 int type
= read_le16(fstream
);
242 /* mono or stereo data */
243 int channels
= read_le16(fstream
);
245 /* sample frequency */
246 samplerate
= read_le32(fstream
);
248 /* skip four bytes */
251 /* bytes per block */
252 blockAlign
= read_le16(fstream
);
256 /* bits per sample */
257 sampleSize
= read_le16(fstream
) / 8;
259 format
= GetSampleFormat(channels
, sampleSize
*8, false);
263 else if(memcmp(tag
, "data", 4) == 0)
265 dataStart
= fstream
->tellg();
266 dataLen
= remLen
= length
;
269 fstream
->seekg(length
, std::ios_base::cur
);
272 if(dataStart
> 0 && format
!= AL_NONE
)
273 fstream
->seekg(dataStart
);
280 struct aiffStream
: public alureStream
{
289 virtual bool IsValid()
290 { return (dataStart
> 0 && format
!= AL_NONE
); }
292 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
295 *frequency
= samplerate
;
296 *blockalign
= blockAlign
;
300 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
302 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
303 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
305 std::streamsize got
= fstream
->gcount();
306 got
-= got
%blockAlign
;
313 for(std::streamsize i
= 0;i
< got
;i
+=2)
314 swap(data
[i
], data
[i
+1]);
316 else if(sampleSize
== 4)
318 for(std::streamsize i
= 0;i
< got
;i
+=4)
320 swap(data
[i
+0], data
[i
+3]);
321 swap(data
[i
+1], data
[i
+2]);
329 virtual bool Rewind()
332 if(fstream
->seekg(dataStart
))
338 SetError("Seek failed");
342 aiffStream(std::istream
*_fstream
)
343 : alureStream(_fstream
), format(0), dataStart(0)
348 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
349 memcmp(buffer
, "FORM", 4) != 0 || memcmp(buffer
+8, "AIFF", 4) != 0)
352 while(!dataStart
|| format
== AL_NONE
)
355 if(!fstream
->read(tag
, 4))
358 /* read chunk length */
359 length
= read_be32(fstream
);
361 if(memcmp(tag
, "COMM", 4) == 0 && length
>= 18)
363 /* mono or stereo data */
364 int channels
= read_be16(fstream
);
366 /* number of sample frames */
369 /* bits per sample */
370 sampleSize
= read_be16(fstream
) / 8;
372 /* sample frequency */
373 samplerate
= read_be80extended(fstream
);
375 /* block alignment */
376 blockAlign
= channels
* sampleSize
;
378 format
= GetSampleFormat(channels
, sampleSize
*8, false);
382 else if(memcmp(tag
, "SSND", 4) == 0)
384 dataStart
= fstream
->tellg();
386 dataLen
= remLen
= length
- 8;
389 fstream
->seekg(length
, std::ios_base::cur
);
392 if(dataStart
> 0 && format
!= AL_NONE
)
393 fstream
->seekg(dataStart
);
396 virtual ~aiffStream()
401 struct sndStream
: public alureStream
{
406 virtual bool IsValid()
407 { return sndFile
!= NULL
; }
409 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
411 if(format
== AL_NONE
)
412 format
= GetSampleFormat(sndInfo
.channels
, 16, false);
414 *frequency
= sndInfo
.samplerate
;
415 *blockalign
= sndInfo
.channels
*2;
419 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
421 const ALuint frameSize
= 2*sndInfo
.channels
;
422 return psf_readf_short(sndFile
, (short*)data
, bytes
/frameSize
) * frameSize
;
425 virtual bool Rewind()
427 if(psf_seek(sndFile
, 0, SEEK_SET
) != -1)
430 SetError("Seek failed");
434 sndStream(std::istream
*_fstream
)
435 : alureStream(_fstream
), sndFile(NULL
), format(AL_NONE
)
437 memset(&sndInfo
, 0, sizeof(sndInfo
));
439 if(!sndfile_handle
) return;
441 static SF_VIRTUAL_IO streamIO
= {
445 sndFile
= psf_open_virtual(&streamIO
, SFM_READ
, &sndInfo
, this);
456 // libSndFile iostream callbacks
457 static sf_count_t
get_filelen(void *user_data
)
459 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
462 std::streampos len
= -1;
463 std::streampos pos
= stream
->tellg();
464 if(stream
->seekg(0, std::ios_base::end
))
466 len
= stream
->tellg();
473 static sf_count_t
seek(sf_count_t offset
, int whence
, void *user_data
)
475 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
478 if(whence
== SEEK_CUR
)
479 stream
->seekg(offset
, std::ios_base::cur
);
480 else if(whence
== SEEK_SET
)
481 stream
->seekg(offset
, std::ios_base::beg
);
482 else if(whence
== SEEK_END
)
483 stream
->seekg(offset
, std::ios_base::end
);
487 return stream
->tellg();
490 static sf_count_t
read(void *ptr
, sf_count_t count
, void *user_data
)
492 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
494 stream
->read(static_cast<char*>(ptr
), count
);
495 return stream
->gcount();
498 static sf_count_t
write(const void*, sf_count_t
, void*)
501 static sf_count_t
tell(void *user_data
)
503 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
505 return stream
->tellg();
509 struct sndStream
: public nullStream
{
510 sndStream(std::istream
*){}
514 #ifdef HAS_VORBISFILE
515 struct oggStream
: public alureStream
{
516 OggVorbis_File oggFile
;
517 vorbis_info
*oggInfo
;
521 virtual bool IsValid()
522 { return oggInfo
!= NULL
; }
524 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
526 if(format
== AL_NONE
)
527 format
= GetSampleFormat(oggInfo
->channels
, 16, false);
529 *frequency
= oggInfo
->rate
;
530 *blockalign
= oggInfo
->channels
*2;
534 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
539 int res
= pov_read(&oggFile
, (char*)&data
[got
], bytes
, BigEndian
?1:0, 2, 1, &oggBitstream
);
545 // 1, 2, and 4 channel files decode into the same channel order as
546 // OpenAL, however 6(5.1), 7(6.1), and 8(7.1) channel files need to be
548 if(oggInfo
->channels
== 6)
550 ALshort
*samples
= (ALshort
*)data
;
551 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=6)
553 // OpenAL : FL, FR, FC, LFE, RL, RR
554 // Vorbis : FL, FC, FR, RL, RR, LFE
555 swap(samples
[i
+1], samples
[i
+2]);
556 swap(samples
[i
+3], samples
[i
+5]);
557 swap(samples
[i
+4], samples
[i
+5]);
560 else if(oggInfo
->channels
== 7)
562 ALshort
*samples
= (ALshort
*)data
;
563 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=7)
565 // OpenAL : FL, FR, FC, LFE, RC, SL, SR
566 // Vorbis : FL, FC, FR, SL, SR, RC, LFE
567 swap(samples
[i
+1], samples
[i
+2]);
568 swap(samples
[i
+3], samples
[i
+6]);
569 swap(samples
[i
+4], samples
[i
+6]);
570 swap(samples
[i
+5], samples
[i
+6]);
573 else if(oggInfo
->channels
== 8)
575 ALshort
*samples
= (ALshort
*)data
;
576 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=8)
578 // OpenAL : FL, FR, FC, LFE, RL, RR, SL, SR
579 // Vorbis : FL, FC, FR, SL, SR, RL, RR, LFE
580 swap(samples
[i
+1], samples
[i
+2]);
581 swap(samples
[i
+3], samples
[i
+7]);
582 swap(samples
[i
+4], samples
[i
+5]);
583 swap(samples
[i
+5], samples
[i
+6]);
584 swap(samples
[i
+6], samples
[i
+7]);
590 virtual bool Rewind()
592 if(pov_pcm_seek(&oggFile
, 0) == 0)
595 SetError("Seek failed");
599 oggStream(std::istream
*_fstream
)
600 : alureStream(_fstream
), oggInfo(NULL
), oggBitstream(0), format(AL_NONE
)
602 if(!vorbisfile_handle
) return;
604 const ov_callbacks streamIO
= {
605 read
, seek
, NULL
, tell
608 if(pov_open_callbacks(this, &oggFile
, NULL
, 0, streamIO
) == 0)
610 oggInfo
= pov_info(&oggFile
, -1);
624 // libVorbisFile iostream callbacks
625 static int seek(void *user_data
, ogg_int64_t offset
, int whence
)
627 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
630 if(whence
== SEEK_CUR
)
631 stream
->seekg(offset
, std::ios_base::cur
);
632 else if(whence
== SEEK_SET
)
633 stream
->seekg(offset
, std::ios_base::beg
);
634 else if(whence
== SEEK_END
)
635 stream
->seekg(offset
, std::ios_base::end
);
639 return stream
->tellg();
642 static size_t read(void *ptr
, size_t size
, size_t nmemb
, void *user_data
)
644 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
647 stream
->read(static_cast<char*>(ptr
), nmemb
*size
);
648 size_t ret
= stream
->gcount();
652 static long tell(void *user_data
)
654 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
656 return stream
->tellg();
660 struct oggStream
: public nullStream
{
661 oggStream(std::istream
*){}
666 struct flacStream
: public alureStream
{
667 FLAC__StreamDecoder
*flacFile
;
673 std::vector
<ALubyte
> initialData
;
679 virtual bool IsValid()
680 { return flacFile
!= NULL
; }
682 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
685 *frequency
= samplerate
;
686 *blockalign
= blockAlign
;
690 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
696 if(initialData
.size() > 0)
698 size_t rem
= std::min(initialData
.size(), (size_t)bytes
);
699 memcpy(data
, &initialData
[0], rem
);
701 initialData
.erase(initialData
.begin(), initialData
.begin()+rem
);
704 while(outTotal
< bytes
)
706 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
707 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
714 virtual bool Rewind()
716 if(pFLAC__stream_decoder_seek_absolute(flacFile
, 0) != false)
722 SetError("Seek failed");
726 flacStream(std::istream
*_fstream
)
727 : alureStream(_fstream
), flacFile(NULL
), format(AL_NONE
), samplerate(0),
728 blockAlign(0), useFloat(AL_FALSE
)
730 if(!flac_handle
) return;
732 flacFile
= pFLAC__stream_decoder_new();
735 if(pFLAC__stream_decoder_init_stream(flacFile
, ReadCallback
, SeekCallback
, TellCallback
, LengthCallback
, EofCallback
, WriteCallback
, MetadataCallback
, ErrorCallback
, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK
)
743 pFLAC__stream_decoder_finish(flacFile
);
745 pFLAC__stream_decoder_delete(flacFile
);
750 virtual ~flacStream()
754 pFLAC__stream_decoder_finish(flacFile
);
755 pFLAC__stream_decoder_delete(flacFile
);
763 // We need to decode some data to be able to get the channel count, bit
764 // depth, and sample rate. It also ensures the file has FLAC data, as
765 // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
769 while(initialData
.size() == 0)
771 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
772 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
776 if(initialData
.size() > 0)
781 static FLAC__StreamDecoderWriteStatus
WriteCallback(const FLAC__StreamDecoder
*, const FLAC__Frame
*frame
, const FLAC__int32
*const buffer
[], void *client_data
)
783 flacStream
*self
= static_cast<flacStream
*>(client_data
);
784 ALubyte
*data
= self
->outBytes
+ self
->outTotal
;
787 if(self
->format
== AL_NONE
)
789 ALuint bps
= frame
->header
.bits_per_sample
;
790 if(bps
== 24 || bps
== 32)
792 self
->format
= GetSampleFormat(frame
->header
.channels
, 32, true);
793 if(self
->format
!= AL_NONE
)
795 self
->useFloat
= AL_TRUE
;
800 if(self
->format
== AL_NONE
)
801 self
->format
= GetSampleFormat(frame
->header
.channels
, bps
, false);
802 self
->blockAlign
= frame
->header
.channels
* bps
/8;
803 self
->samplerate
= frame
->header
.sample_rate
;
806 const ALboolean useFloat
= self
->useFloat
;
807 while(self
->outTotal
< self
->outLen
&& i
< frame
->header
.blocksize
)
809 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
811 if(frame
->header
.bits_per_sample
== 8)
812 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
813 else if(frame
->header
.bits_per_sample
== 16)
814 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
815 else if(frame
->header
.bits_per_sample
== 24)
818 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
819 buffer
[c
][i
]/(float)0x7FFFFF :
820 buffer
[c
][i
]/(float)0x800000);
822 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
824 else if(frame
->header
.bits_per_sample
== 32)
827 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
828 buffer
[c
][i
]/(float)0x7FFFFFFF :
829 buffer
[c
][i
]/(float)0x80000000u
);
831 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
834 self
->outTotal
+= self
->blockAlign
;
835 data
+= self
->blockAlign
;
839 if(i
< frame
->header
.blocksize
)
841 ALuint blocklen
= (frame
->header
.blocksize
-i
) *
843 ALuint start
= self
->initialData
.size();
845 self
->initialData
.resize(start
+blocklen
);
846 data
= &self
->initialData
[start
];
849 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
851 if(frame
->header
.bits_per_sample
== 8)
852 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
853 else if(frame
->header
.bits_per_sample
== 16)
854 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
855 else if(frame
->header
.bits_per_sample
== 24)
858 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
859 buffer
[c
][i
]/(float)0x7FFFFF :
860 buffer
[c
][i
]/(float)0x800000);
862 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
864 else if(frame
->header
.bits_per_sample
== 32)
867 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
868 buffer
[c
][i
]/(float)0x7FFFFFFF :
869 buffer
[c
][i
]/(float)0x80000000u
);
871 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
874 data
+= self
->blockAlign
;
876 } while(i
< frame
->header
.blocksize
);
879 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
881 static void MetadataCallback(const FLAC__StreamDecoder
*,const FLAC__StreamMetadata
*,void*)
884 static void ErrorCallback(const FLAC__StreamDecoder
*,FLAC__StreamDecoderErrorStatus
,void*)
888 static FLAC__StreamDecoderReadStatus
ReadCallback(const FLAC__StreamDecoder
*, FLAC__byte buffer
[], size_t *bytes
, void *client_data
)
890 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
894 return FLAC__STREAM_DECODER_READ_STATUS_ABORT
;
896 stream
->read(reinterpret_cast<char*>(buffer
), *bytes
);
897 *bytes
= stream
->gcount();
898 if(*bytes
== 0 && stream
->eof())
899 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
;
901 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
;
903 static FLAC__StreamDecoderSeekStatus
SeekCallback(const FLAC__StreamDecoder
*, FLAC__uint64 absolute_byte_offset
, void *client_data
)
905 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
908 if(!stream
->seekg(absolute_byte_offset
))
909 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
;
910 return FLAC__STREAM_DECODER_SEEK_STATUS_OK
;
912 static FLAC__StreamDecoderTellStatus
TellCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*absolute_byte_offset
, void *client_data
)
914 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
917 *absolute_byte_offset
= stream
->tellg();
918 return FLAC__STREAM_DECODER_TELL_STATUS_OK
;
920 static FLAC__StreamDecoderLengthStatus
LengthCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*stream_length
, void *client_data
)
922 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
925 std::streampos pos
= stream
->tellg();
926 if(stream
->seekg(0, std::ios_base::end
))
928 *stream_length
= stream
->tellg();
933 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
;
934 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK
;
936 static FLAC__bool
EofCallback(const FLAC__StreamDecoder
*, void *client_data
)
938 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
939 return (stream
->eof()) ? true : false;
943 struct flacStream
: public nullStream
{
944 flacStream(std::istream
*){}
950 struct mp3Stream
: public alureStream
{
951 mpg123_handle
*mp3File
;
956 virtual bool IsValid()
957 { return mp3File
!= NULL
; }
959 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
962 *frequency
= samplerate
;
963 *blockalign
= channels
*2;
967 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
973 int ret
= pmpg123_read(mp3File
, data
, bytes
, &got
);
979 if(ret
== MPG123_NEW_FORMAT
)
983 pmpg123_getformat(mp3File
, &newrate
, &newchans
, &enc
);
986 if(ret
== MPG123_NEED_MORE
)
988 unsigned char data
[4096];
989 fstream
->read((char*)data
, sizeof(data
));
990 std::streamsize insize
= fstream
->gcount();
991 if(insize
> 0 && pmpg123_feed(mp3File
, data
, insize
) == MPG123_OK
)
1000 virtual bool Rewind()
1003 std::istream::pos_type oldpos
= fstream
->tellg();
1006 mpg123_handle
*newFile
= pmpg123_new(NULL
, NULL
);
1007 if(pmpg123_open_feed(newFile
) == MPG123_OK
)
1009 unsigned char data
[4096];
1014 ALuint amt
, total
= 0;
1016 fstream
->read((char*)data
, sizeof(data
));
1017 amt
= fstream
->gcount();
1020 ret
= pmpg123_decode(newFile
, data
, amt
, NULL
, 0, NULL
);
1021 } while(ret
== MPG123_NEED_MORE
&& total
< 64*1024);
1023 if(ret
== MPG123_NEW_FORMAT
&&
1024 pmpg123_getformat(newFile
, &newrate
, &newchans
, &enc
) == MPG123_OK
)
1026 if(pmpg123_format_none(newFile
) == MPG123_OK
&&
1027 pmpg123_format(newFile
, samplerate
, channels
, MPG123_ENC_SIGNED_16
) == MPG123_OK
)
1030 pmpg123_delete(mp3File
);
1035 pmpg123_delete(newFile
);
1038 fstream
->seekg(oldpos
);
1039 SetError("Restart failed");
1043 mp3Stream(std::istream
*_fstream
)
1044 : alureStream(_fstream
), mp3File(NULL
), format(AL_NONE
)
1046 if(!mp123_handle
) return;
1048 mp3File
= pmpg123_new(NULL
, NULL
);
1049 if(pmpg123_open_feed(mp3File
) == MPG123_OK
)
1051 unsigned char data
[4096];
1054 ALuint amt
, total
= 0;
1056 fstream
->read((char*)data
, sizeof(data
));
1057 amt
= fstream
->gcount();
1060 ret
= pmpg123_decode(mp3File
, data
, amt
, NULL
, 0, NULL
);
1061 } while(ret
== MPG123_NEED_MORE
&& total
< 64*1024);
1063 if(ret
== MPG123_NEW_FORMAT
&&
1064 pmpg123_getformat(mp3File
, &samplerate
, &channels
, &enc
) == MPG123_OK
)
1066 format
= GetSampleFormat(channels
, 16, false);
1067 if(pmpg123_format_none(mp3File
) == MPG123_OK
&&
1068 pmpg123_format(mp3File
, samplerate
, channels
, MPG123_ENC_SIGNED_16
) == MPG123_OK
)
1075 pmpg123_delete(mp3File
);
1079 virtual ~mp3Stream()
1082 pmpg123_delete(mp3File
);
1087 struct mp3Stream
: public nullStream
{
1088 mp3Stream(std::istream
*){}
1094 struct dumbStream
: public alureStream
{
1095 DUMBFILE_SYSTEM vfs
;
1098 DUH_SIGRENDERER
*renderer
;
1099 std::vector
<sample_t
> sampleBuf
;
1104 virtual bool IsValid()
1105 { return renderer
!= NULL
; }
1107 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1109 if(format
== AL_NONE
)
1111 format
= GetSampleFormat(2, 32, true);
1112 if(format
== AL_NONE
)
1113 format
= AL_FORMAT_STEREO16
;
1117 *blockalign
= 2 * ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) :
1122 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1126 if(pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(renderer
)) == 0)
1129 ALuint sample_count
= bytes
/ ((format
==AL_FORMAT_STEREO16
) ?
1130 sizeof(ALshort
) : sizeof(ALfloat
));
1132 sampleBuf
.resize(sample_count
);
1133 sample_t
*samples
[] = {
1137 pdumb_silence(samples
[0], sample_count
);
1138 ret
= pduh_sigrenderer_generate_samples(renderer
, 1.0f
, 1.0f
, sample_count
/2, samples
);
1140 if(format
== AL_FORMAT_STEREO16
)
1142 for(ALuint i
= 0;i
< ret
;i
++)
1143 ((ALshort
*)data
)[i
] = clamp(samples
[0][i
]>>8, -32768, 32767);
1147 for(ALuint i
= 0;i
< ret
;i
++)
1148 ((ALfloat
*)data
)[i
] = ((samples
[0][i
]>=0) ?
1149 samples
[0][i
]/(float)0x7FFFFF :
1150 samples
[0][i
]/(float)0x800000);
1152 ret
*= ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) : sizeof(ALfloat
));
1157 virtual bool Rewind()
1161 // If a previous speed was recorded, the stream tried to loop. So
1162 // let it loop on a rewind request.
1163 pdumb_it_sr_set_speed(pduh_get_it_sigrenderer(renderer
), prevSpeed
);
1168 // Else, no loop point. Restart from scratch.
1169 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
1172 SetError("Could start renderer");
1175 pduh_end_sigrenderer(renderer
);
1176 renderer
= newrenderer
;
1180 virtual bool SetOrder(ALuint order
)
1182 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, order
);
1185 SetError("Could not set order");
1188 pduh_end_sigrenderer(renderer
);
1189 renderer
= newrenderer
;
1195 dumbStream(std::istream
*_fstream
)
1196 : alureStream(_fstream
), dumbFile(NULL
), duh(NULL
), renderer(NULL
),
1197 lastOrder(0), prevSpeed(0), format(AL_NONE
)
1199 if(!dumb_handle
) return;
1201 DUH
* (*funcs
[])(DUMBFILE
*) = {
1211 vfs
.getc
= read_char
;
1215 for(size_t i
= 0;funcs
[i
];i
++)
1217 dumbFile
= pdumbfile_open_ex(this, &vfs
);
1220 duh
= funcs
[i
](dumbFile
);
1223 renderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
1226 pdumb_it_set_loop_callback(pduh_get_it_sigrenderer(renderer
), loop_cb
, this);
1234 pdumbfile_close(dumbFile
);
1242 virtual ~dumbStream()
1245 pduh_end_sigrenderer(renderer
);
1253 pdumbfile_close(dumbFile
);
1258 // DUMBFILE iostream callbacks
1259 static int skip(void *user_data
, long offset
)
1261 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1264 if(stream
->seekg(offset
, std::ios_base::cur
))
1269 static long read(char *ptr
, long size
, void *user_data
)
1271 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1274 stream
->read(ptr
, size
);
1275 return stream
->gcount();
1278 static int read_char(void *user_data
)
1280 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1284 stream
->read(reinterpret_cast<char*>(&ret
), 1);
1285 if(stream
->gcount() > 0)
1290 static int loop_cb(void *user_data
)
1292 dumbStream
*self
= static_cast<dumbStream
*>(user_data
);
1293 self
->prevSpeed
= pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(self
->renderer
));
1294 pdumb_it_sr_set_speed(pduh_get_it_sigrenderer(self
->renderer
), 0);
1299 struct dumbStream
: public nullStream
{
1300 dumbStream(std::istream
*){}
1306 struct midiStream
: public alureStream
{
1311 #define INVALID_HANDLE_VALUE (-1)
1317 virtual bool IsValid()
1318 { return cpid
!= INVALID_HANDLE_VALUE
; }
1320 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1322 *fmt
= AL_FORMAT_STEREO16
;
1328 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1335 if(!ReadFile(pcmFile
, data
, bytes
, &got
, NULL
))
1339 while((got
=read(pcmFile
, &data
[total
], bytes
)) == -1 && errno
== EINTR
)
1350 for(ALuint i
= 0;i
< total
;i
+=2)
1351 swap(data
[i
], data
[i
+1]);
1357 virtual bool Rewind()
1363 HANDLE _pcmFile
, _cpid
;
1364 if(!StartStream(_pcmFile
, _cpid
))
1366 SetError("Failed to restart timidity");
1370 TerminateProcess(cpid
, 0);
1374 CloseHandle(pcmFile
);
1377 int _pcmFile
; pid_t _cpid
;
1378 if(!StartStream(_pcmFile
, _cpid
))
1380 SetError("Failed to restart timidity");
1384 kill(cpid
, SIGTERM
);
1385 waitpid(cpid
, NULL
, 0);
1395 midiStream(std::istream
*_fstream
)
1396 : alureStream(_fstream
), pcmFile(INVALID_HANDLE_VALUE
),
1397 cpid(INVALID_HANDLE_VALUE
), Freq(44100)
1399 ALCcontext
*ctx
= alcGetCurrentContext();
1400 ALCdevice
*dev
= alcGetContextsDevice(ctx
);
1401 alcGetIntegerv(dev
, ALC_FREQUENCY
, 1, &Freq
);
1403 StartStream(pcmFile
, cpid
);
1406 virtual ~midiStream()
1408 if(cpid
!= INVALID_HANDLE_VALUE
)
1411 TerminateProcess(cpid
, 0);
1414 kill(cpid
, SIGTERM
);
1415 waitpid(cpid
, NULL
, 0);
1417 cpid
= INVALID_HANDLE_VALUE
;
1420 if(pcmFile
!= INVALID_HANDLE_VALUE
)
1423 CloseHandle(pcmFile
);
1427 pcmFile
= INVALID_HANDLE_VALUE
;
1433 bool StartStream(HANDLE
&pcmFile
, HANDLE
&cpid
)
1435 bool StartStream(int &pcmFile
, pid_t
&cpid
)
1439 std::vector
<ALubyte
> midiData
;
1441 fstream
->read(hdr
, sizeof(hdr
));
1442 if(fstream
->gcount() != sizeof(hdr
))
1445 if(memcmp(hdr
, "MThd", 4) == 0)
1448 for(size_t i
= 0;i
< sizeof(hdr
);i
++)
1449 midiData
.push_back(hdr
[i
]);
1450 while(fstream
->get(ch
))
1451 midiData
.push_back(ch
);
1453 else if(memcmp(hdr
, "MUS\x1a", sizeof(hdr
)) == 0)
1455 if(!ConvertMUS(midiData
))
1462 SECURITY_ATTRIBUTES attr
;
1463 attr
.nLength
= sizeof(attr
);
1464 attr
.bInheritHandle
= TRUE
;
1465 attr
.lpSecurityDescriptor
= NULL
;
1467 HANDLE midPipe
[2], pcmPipe
[2];
1468 if(!CreatePipe(&midPipe
[0], &midPipe
[1], &attr
, 0))
1470 if(!CreatePipe(&pcmPipe
[0], &pcmPipe
[1], &attr
, 0))
1472 CloseHandle(midPipe
[0]);
1473 CloseHandle(midPipe
[1]);
1477 PROCESS_INFORMATION procInfo
;
1478 memset(&procInfo
, 0, sizeof(procInfo
));
1480 STARTUPINFO startInfo
;
1481 memset(&startInfo
, 0, sizeof(startInfo
));
1482 startInfo
.cb
= sizeof(startInfo
);
1483 startInfo
.hStdError
= GetStdHandle(STD_ERROR_HANDLE
);
1484 startInfo
.hStdOutput
= pcmPipe
[1];
1485 startInfo
.hStdInput
= midPipe
[0];
1486 startInfo
.dwFlags
|= STARTF_USESTDHANDLES
;
1488 std::stringstream cmdstr
;
1489 cmdstr
<< "timidity - -idqq -Ow1sl -o - -s " << Freq
;
1490 std::string cmdline
= cmdstr
.str();
1492 if(!CreateProcessA(NULL
, const_cast<CHAR
*>(cmdline
.c_str()), NULL
,
1493 NULL
, TRUE
, 0, NULL
, NULL
, &startInfo
, &procInfo
))
1495 CloseHandle(midPipe
[0]);
1496 CloseHandle(midPipe
[1]);
1497 CloseHandle(pcmPipe
[0]);
1498 CloseHandle(pcmPipe
[1]);
1502 CloseHandle(midPipe
[0]);
1503 CloseHandle(pcmPipe
[1]);
1505 CloseHandle(procInfo
.hThread
);
1506 HANDLE pid
= procInfo
.hProcess
;
1508 ALubyte
*cur
= &midiData
[0];
1509 size_t rem
= midiData
.size();
1512 if(!WriteFile(midPipe
[1], cur
, rem
, &wrote
, NULL
) ||
1518 CloseHandle(midPipe
[1]); midPipe
[1] = INVALID_HANDLE_VALUE
;
1522 rem
= sizeof(fmthdr
);
1525 if(!ReadFile(pcmPipe
[0], cur
, rem
, &got
, NULL
) ||
1533 TerminateProcess(pid
, 0);
1535 CloseHandle(pcmPipe
[0]);
1539 int midPipe
[2], pcmPipe
[2];
1540 if(pipe(midPipe
) == -1)
1542 if(pipe(pcmPipe
) == -1)
1561 if(dup2(midPipe
[0], STDIN_FILENO
) != -1 &&
1562 dup2(pcmPipe
[1], STDOUT_FILENO
) != -1)
1569 std::stringstream freqstr
;
1572 execlp("timidity","timidity","-","-idqq","-Ow1sl","-o","-",
1573 "-s", freqstr
.str().c_str(), NULL
);
1578 close(midPipe
[0]); midPipe
[0] = -1;
1579 close(pcmPipe
[1]); pcmPipe
[1] = -1;
1581 void (*oldhandler
)(int) = signal(SIGPIPE
, SIG_IGN
);
1582 ALubyte
*cur
= &midiData
[0];
1583 size_t rem
= midiData
.size();
1586 while((wrote
=write(midPipe
[1], cur
, rem
)) == -1 && errno
== EINTR
)
1593 close(midPipe
[1]); midPipe
[1] = -1;
1594 signal(SIGPIPE
, oldhandler
);
1598 rem
= sizeof(fmthdr
);
1601 while((got
=read(pcmPipe
[0], cur
, rem
)) == -1 && errno
== EINTR
)
1611 waitpid(pid
, NULL
, 0);
1617 pcmFile
= pcmPipe
[0];
1622 alureUInt64
ReadVarLen()
1624 alureUInt64 val
= 0;
1628 if(!fstream
->get(ch
))
1630 val
= (val
<<7) | (ch
&0x7f);
1636 void WriteVarLen(std::vector
<ALubyte
> &out
, alureUInt64 val
)
1638 alureUInt64 buffer
= val
&0x7f;
1639 while((val
>>=7) > 0)
1640 buffer
= (buffer
<<8) | 0x80 | (val
&0x7f);
1643 out
.push_back(buffer
&0xff);
1650 static const ALubyte MIDI_SYSEX
= 0xF0; // SysEx begin
1651 static const ALubyte MIDI_SYSEXEND
= 0xF7; // SysEx end
1652 static const ALubyte MIDI_META
= 0xFF; // Meta event begin
1653 static const ALubyte MIDI_META_TEMPO
= 0x51;
1654 static const ALubyte MIDI_META_EOT
= 0x2F; // End-of-track
1655 static const ALubyte MIDI_META_SSPEC
= 0x7F; // System-specific event
1657 static const ALubyte MIDI_NOTEOFF
= 0x80; // + note + velocity
1658 static const ALubyte MIDI_NOTEON
= 0x90; // + note + velocity
1659 static const ALubyte MIDI_POLYPRESS
= 0xA0; // + pressure (2 bytes)
1660 static const ALubyte MIDI_CTRLCHANGE
= 0xB0; // + ctrlr + value
1661 static const ALubyte MIDI_PRGMCHANGE
= 0xC0; // + new patch
1662 static const ALubyte MIDI_CHANPRESS
= 0xD0; // + pressure (1 byte)
1663 static const ALubyte MIDI_PITCHBEND
= 0xE0; // + pitch bend (2 bytes)
1665 static const ALubyte MUS_EVENT_CHANNEL_MASK
= 0x0F;
1666 static const ALubyte MUS_EVENT_DELTA_MASK
= 0x80;
1668 static const ALubyte MUS_NOTEOFF
= 0x00;
1669 static const ALubyte MUS_NOTEON
= 0x10;
1670 static const ALubyte MUS_PITCHBEND
= 0x20;
1671 static const ALubyte MUS_SYSEVENT
= 0x30;
1672 static const ALubyte MUS_CTRLCHANGE
= 0x40;
1673 static const ALubyte MUS_SCOREEND
= 0x60;
1675 bool ConvertMUS(std::vector
<ALubyte
> &midiData
)
1677 static const ALubyte CtrlTranslate
[15] = {
1678 0, // program change
1680 1, // modulation pot
1683 11, // expression pot
1686 64, // sustain pedal
1688 120, // all sounds off
1689 123, // all notes off
1692 121 // reset all controllers
1695 static const ALubyte MIDIhead
[22] = {
1696 'M','T','h','d', 0, 0, 0, 6,
1697 0, 0, // format 0: only one track
1698 0, 1, // yes, there is really only one track
1699 0, 70, // 70 divisions
1700 'M','T','r','k', 0xFF, 0xFF, 0xFF, 0xFF
1703 // The MUS\x1a ID was already read and verified
1704 ALushort songLen
= read_le16(fstream
);
1705 ALushort songStart
= read_le16(fstream
);
1706 ALushort numChans
= read_le16(fstream
);
1708 // Sanity check the MUS file's channel count
1712 fstream
->seekg(songStart
);
1713 std::streamsize maxmus_p
= songLen
;
1714 maxmus_p
+= fstream
->tellg();
1716 ALubyte chanVel
[16];
1717 for(size_t i
= 0;i
< 16;i
++)
1721 for(size_t i
= 0;i
< 16;i
++)
1724 alureUInt64 deltaTime
= 0;
1729 for(size_t i
= 0;i
< sizeof(MIDIhead
);i
++)
1730 midiData
.push_back(MIDIhead
[i
]);
1732 // The first event sets the tempo to 500,000 microsec/quarter note
1733 midiData
.push_back(0);
1734 midiData
.push_back(MIDI_META
| 0);
1735 midiData
.push_back(MIDI_META_TEMPO
| 0);
1736 midiData
.push_back(3);
1737 midiData
.push_back(0x07);
1738 midiData
.push_back(0xA1);
1739 midiData
.push_back(0x20);
1741 while(fstream
->good() && fstream
->tellg() < maxmus_p
&& event
!= MUS_SCOREEND
)
1743 event
= fstream
->get();
1745 bool hasDelta
= event
&MUS_EVENT_DELTA_MASK
;
1746 ALubyte channel
= event
&MUS_EVENT_CHANNEL_MASK
;
1748 event
&= ~MUS_EVENT_DELTA_MASK
;
1749 event
&= ~MUS_EVENT_CHANNEL_MASK
;
1751 // Convert percussion channel (MUS #15 -> MIDI #9)
1754 else if(channel
>= 9)
1757 if(firstUse
[channel
])
1759 // This is the first time this channel has been used,
1760 // so sets its volume to 127.
1761 firstUse
[channel
] = false;
1762 midiData
.push_back(0);
1763 midiData
.push_back(MIDI_CTRLCHANGE
| channel
);
1764 midiData
.push_back(7);
1765 midiData
.push_back(127);
1769 if(event
!= MUS_SCOREEND
)
1772 ALubyte midArgs
= 2;
1773 ALubyte midStatus
= channel
;
1774 ALubyte mid1
= 0, mid2
= 0;
1780 midStatus
|= MIDI_NOTEOFF
;
1786 midStatus
|= MIDI_NOTEON
;
1789 chanVel
[channel
] = fstream
->get()&0x7f;
1790 mid2
= chanVel
[channel
];
1794 midStatus
|= MIDI_PITCHBEND
;
1796 mid2
= (t
>>1) & 0x7f;
1800 if(t
< 10 || t
> 14)
1804 midStatus
|= MIDI_CTRLCHANGE
;
1805 mid1
= CtrlTranslate
[t
];
1806 mid2
= ((t
==12) /* Mono */ ? numChans
: 0);
1810 case MUS_CTRLCHANGE
:
1813 // Program change, only one arg
1815 midStatus
|= MIDI_PRGMCHANGE
;
1816 mid1
= fstream
->get()&0x7f;
1820 midStatus
|= MIDI_CTRLCHANGE
;
1821 mid1
= CtrlTranslate
[t
];
1822 mid2
= fstream
->get();
1829 midStatus
= MIDI_META
;
1830 mid1
= MIDI_META_EOT
;
1840 // A system-specific event with no data is a no-op.
1841 midStatus
= MIDI_META
;
1842 mid1
= MIDI_META_SSPEC
;
1846 WriteVarLen(midiData
, deltaTime
);
1847 if(midStatus
!= status
)
1850 midiData
.push_back(status
);
1853 midiData
.push_back(mid1
);
1855 midiData
.push_back(mid2
);
1857 deltaTime
= (hasDelta
? ReadVarLen() : 0);
1860 // If reading failed or we overran the song length, the song is bad
1861 if(!fstream
->good() || fstream
->tellg() > maxmus_p
)
1864 // Fill in track length
1865 size_t trackLen
= midiData
.size() - 22;
1866 midiData
[18] = (trackLen
>>24) & 0xff;
1867 midiData
[19] = (trackLen
>>16) & 0xff;
1868 midiData
[20] = (trackLen
>>8) & 0xff;
1869 midiData
[21] = trackLen
&0xff;
1874 struct midiStream
: public nullStream
{
1875 midiStream(std::istream
*){}
1880 template <typename T
>
1881 alureStream
*get_stream_decoder(const T
&fdata
)
1883 alureStream
*stream
;
1885 std::map
<ALint
,UserCallbacks
>::iterator i
= InstalledCallbacks
.begin();
1886 while(i
!= InstalledCallbacks
.end() && i
->first
< 0)
1888 stream
= new customStream(fdata
, i
->second
);
1889 if(stream
->IsValid())
1895 std::istream
*file
= new InStream(fdata
);
1898 stream
= new wavStream(file
);
1899 if(stream
->IsValid())
1904 file
->seekg(0, std::ios_base::beg
);
1905 stream
= new aiffStream(file
);
1906 if(stream
->IsValid())
1910 // Try libVorbisFile
1912 file
->seekg(0, std::ios_base::beg
);
1913 stream
= new oggStream(file
);
1914 if(stream
->IsValid())
1920 file
->seekg(0, std::ios_base::beg
);
1921 stream
= new flacStream(file
);
1922 if(stream
->IsValid())
1928 file
->seekg(0, std::ios_base::beg
);
1929 stream
= new dumbStream(file
);
1930 if(stream
->IsValid())
1936 file
->seekg(0, std::ios_base::beg
);
1937 stream
= new sndStream(file
);
1938 if(stream
->IsValid())
1944 file
->seekg(0, std::ios_base::beg
);
1945 stream
= new mp3Stream(file
);
1946 if(stream
->IsValid())
1952 file
->seekg(0, std::ios_base::beg
);
1953 stream
= new midiStream(file
);
1954 if(stream
->IsValid())
1958 SetError("Unsupported type");
1963 SetError("Failed to open file");
1967 while(i
!= InstalledCallbacks
.end())
1969 stream
= new customStream(fdata
, i
->second
);
1970 if(stream
->IsValid())
1976 return new nullStream
;
1979 alureStream
*create_stream(const char *fname
)
1980 { return get_stream_decoder(fname
); }
1981 alureStream
*create_stream(const MemDataInfo
&memData
)
1982 { return get_stream_decoder(memData
); }
1984 alureStream
*create_stream(ALvoid
*userdata
, ALenum format
, ALuint rate
, const UserCallbacks
&cb
)
1985 { return new customStream(userdata
, format
, rate
, cb
); }