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
)
112 !cb
.get_fmt(usrFile
, &this->format
, &samplerate
, &blockAlign
))
117 *frequency
= samplerate
;
118 *blockalign
= blockAlign
;
122 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
123 { return cb
.decode(usrFile
, data
, bytes
); }
125 virtual bool Rewind()
127 if(cb
.rewind
&& cb
.rewind(usrFile
))
129 SetError("Rewind failed");
133 customStream(const char *fname
, const UserCallbacks
&callbacks
)
134 : alureStream(NULL
), usrFile(NULL
), format(0), samplerate(0),
135 blockAlign(0), cb(callbacks
)
136 { if(cb
.open_file
) usrFile
= cb
.open_file(fname
); }
138 customStream(const MemDataInfo
&memData
, const UserCallbacks
&callbacks
)
139 : alureStream(NULL
), usrFile(NULL
), format(0), samplerate(0),
140 blockAlign(0), memInfo(memData
), cb(callbacks
)
141 { if(cb
.open_mem
) usrFile
= cb
.open_mem(memInfo
.Data
, memInfo
.Length
); }
143 customStream(void *userdata
, ALenum fmt
, ALuint srate
, const UserCallbacks
&callbacks
)
144 : alureStream(NULL
), usrFile(userdata
), format(fmt
), samplerate(srate
),
145 blockAlign(DetectBlockAlignment(format
)), cb(callbacks
)
148 virtual ~customStream()
150 if(cb
.close
&& usrFile
)
157 struct wavStream
: public alureStream
{
166 virtual bool IsValid()
167 { return (dataStart
> 0 && format
!= AL_NONE
); }
169 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
172 *frequency
= samplerate
;
173 *blockalign
= blockAlign
;
177 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
179 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
180 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
182 std::streamsize got
= fstream
->gcount();
183 got
-= got
%blockAlign
;
186 if(BigEndian
&& sampleSize
== 16)
188 for(std::streamsize i
= 0;i
< got
;i
+=2)
189 swap(data
[i
], data
[i
+1]);
191 else if(BigEndian
&& sampleSize
== 32)
193 for(std::streamsize i
= 0;i
< got
;i
+=4)
195 swap(data
[i
+0], data
[i
+3]);
196 swap(data
[i
+1], data
[i
+2]);
199 else if(BigEndian
&& sampleSize
== 64)
201 for(std::streamsize i
= 0;i
< got
;i
+=8)
203 swap(data
[i
+0], data
[i
+7]);
204 swap(data
[i
+1], data
[i
+6]);
205 swap(data
[i
+2], data
[i
+5]);
206 swap(data
[i
+3], data
[i
+4]);
213 virtual bool Rewind()
216 if(fstream
->seekg(dataStart
))
222 SetError("Seek failed");
226 wavStream(std::istream
*_fstream
)
227 : alureStream(_fstream
), format(0), dataStart(0)
232 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
233 memcmp(buffer
, "RIFF", 4) != 0 || memcmp(buffer
+8, "WAVE", 4) != 0)
236 while(!dataStart
|| format
== AL_NONE
)
239 if(!fstream
->read(tag
, 4))
242 /* read chunk length */
243 length
= read_le32(fstream
);
245 if(memcmp(tag
, "fmt ", 4) == 0 && length
>= 16)
247 /* Data type (should be 1 for PCM data, 3 for float PCM data,
248 * and 17 for IMA4 data) */
249 int type
= read_le16(fstream
);
250 if(type
!= 0x0001 && type
!= 0x0003 && type
!= 0x0011)
253 /* mono or stereo data */
254 int channels
= read_le16(fstream
);
256 /* sample frequency */
257 samplerate
= read_le32(fstream
);
259 /* skip four bytes */
262 /* bytes per block */
263 blockAlign
= read_le16(fstream
);
267 /* bits per sample */
268 sampleSize
= read_le16(fstream
);
272 /* Look for any extra data and try to find the format */
276 extrabytes
= read_le16(fstream
);
279 extrabytes
= std::min(extrabytes
, length
);
282 format
= GetSampleFormat(channels
, sampleSize
, false);
283 else if(type
== 0x0003)
284 format
= GetSampleFormat(channels
, sampleSize
, true);
285 else if(type
== 0x0011 && extrabytes
>= 2)
287 int samples
= read_le16(fstream
);
290 /* AL_EXT_IMA4 only supports 36 bytes-per-channel block
291 * alignment, which has 65 uncompressed sample frames */
292 if(blockAlign
== 36*channels
&& samples
== 65*channels
&&
293 alIsExtensionPresent("AL_EXT_IMA4"))
296 format
= AL_FORMAT_MONO_IMA4
;
297 else if(channels
== 2)
298 format
= AL_FORMAT_STEREO_IMA4
;
302 else if(memcmp(tag
, "data", 4) == 0)
304 dataStart
= fstream
->tellg();
305 dataLen
= remLen
= length
;
308 fstream
->seekg(length
, std::ios_base::cur
);
311 if(dataStart
> 0 && format
!= AL_NONE
)
312 fstream
->seekg(dataStart
);
319 struct aiffStream
: public alureStream
{
328 virtual bool IsValid()
329 { return (dataStart
> 0 && format
!= AL_NONE
); }
331 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
334 *frequency
= samplerate
;
335 *blockalign
= blockAlign
;
339 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
341 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
342 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
344 std::streamsize got
= fstream
->gcount();
345 got
-= got
%blockAlign
;
352 for(std::streamsize i
= 0;i
< got
;i
+=2)
353 swap(data
[i
], data
[i
+1]);
355 else if(sampleSize
== 4)
357 for(std::streamsize i
= 0;i
< got
;i
+=4)
359 swap(data
[i
+0], data
[i
+3]);
360 swap(data
[i
+1], data
[i
+2]);
368 virtual bool Rewind()
371 if(fstream
->seekg(dataStart
))
377 SetError("Seek failed");
381 aiffStream(std::istream
*_fstream
)
382 : alureStream(_fstream
), format(0), dataStart(0)
387 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
388 memcmp(buffer
, "FORM", 4) != 0 || memcmp(buffer
+8, "AIFF", 4) != 0)
391 while(!dataStart
|| format
== AL_NONE
)
394 if(!fstream
->read(tag
, 4))
397 /* read chunk length */
398 length
= read_be32(fstream
);
400 if(memcmp(tag
, "COMM", 4) == 0 && length
>= 18)
402 /* mono or stereo data */
403 int channels
= read_be16(fstream
);
405 /* number of sample frames */
408 /* bits per sample */
409 sampleSize
= read_be16(fstream
) / 8;
411 /* sample frequency */
412 samplerate
= read_be80extended(fstream
);
414 /* block alignment */
415 blockAlign
= channels
* sampleSize
;
417 format
= GetSampleFormat(channels
, sampleSize
*8, false);
421 else if(memcmp(tag
, "SSND", 4) == 0)
423 dataStart
= fstream
->tellg();
425 dataLen
= remLen
= length
- 8;
428 fstream
->seekg(length
, std::ios_base::cur
);
431 if(dataStart
> 0 && format
!= AL_NONE
)
432 fstream
->seekg(dataStart
);
435 virtual ~aiffStream()
440 struct sndStream
: public alureStream
{
445 virtual bool IsValid()
446 { return sndFile
!= NULL
; }
448 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
450 if(format
== AL_NONE
)
451 format
= GetSampleFormat(sndInfo
.channels
, 16, false);
453 *frequency
= sndInfo
.samplerate
;
454 *blockalign
= sndInfo
.channels
*2;
458 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
460 const ALuint frameSize
= 2*sndInfo
.channels
;
461 return psf_readf_short(sndFile
, (short*)data
, bytes
/frameSize
) * frameSize
;
464 virtual bool Rewind()
466 if(psf_seek(sndFile
, 0, SEEK_SET
) != -1)
469 SetError("Seek failed");
473 sndStream(std::istream
*_fstream
)
474 : alureStream(_fstream
), sndFile(NULL
), format(AL_NONE
)
476 memset(&sndInfo
, 0, sizeof(sndInfo
));
478 if(!sndfile_handle
) return;
480 static SF_VIRTUAL_IO streamIO
= {
484 sndFile
= psf_open_virtual(&streamIO
, SFM_READ
, &sndInfo
, this);
495 // libSndFile iostream callbacks
496 static sf_count_t
get_filelen(void *user_data
)
498 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
501 std::streampos len
= -1;
502 std::streampos pos
= stream
->tellg();
503 if(stream
->seekg(0, std::ios_base::end
))
505 len
= stream
->tellg();
512 static sf_count_t
seek(sf_count_t offset
, int whence
, void *user_data
)
514 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
517 if(whence
== SEEK_CUR
)
518 stream
->seekg(offset
, std::ios_base::cur
);
519 else if(whence
== SEEK_SET
)
520 stream
->seekg(offset
, std::ios_base::beg
);
521 else if(whence
== SEEK_END
)
522 stream
->seekg(offset
, std::ios_base::end
);
526 return stream
->tellg();
529 static sf_count_t
read(void *ptr
, sf_count_t count
, void *user_data
)
531 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
533 stream
->read(static_cast<char*>(ptr
), count
);
534 return stream
->gcount();
537 static sf_count_t
write(const void*, sf_count_t
, void*)
540 static sf_count_t
tell(void *user_data
)
542 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
544 return stream
->tellg();
548 struct sndStream
: public nullStream
{
549 sndStream(std::istream
*){}
553 #ifdef HAS_VORBISFILE
554 struct oggStream
: public alureStream
{
555 OggVorbis_File oggFile
;
556 vorbis_info
*oggInfo
;
560 virtual bool IsValid()
561 { return oggInfo
!= NULL
; }
563 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
565 if(format
== AL_NONE
)
566 format
= GetSampleFormat(oggInfo
->channels
, 16, false);
568 *frequency
= oggInfo
->rate
;
569 *blockalign
= oggInfo
->channels
*2;
573 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
578 int res
= pov_read(&oggFile
, (char*)&data
[got
], bytes
, BigEndian
?1:0, 2, 1, &oggBitstream
);
584 // 1, 2, and 4 channel files decode into the same channel order as
585 // OpenAL, however 6(5.1), 7(6.1), and 8(7.1) channel files need to be
587 if(oggInfo
->channels
== 6)
589 ALshort
*samples
= (ALshort
*)data
;
590 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=6)
592 // OpenAL : FL, FR, FC, LFE, RL, RR
593 // Vorbis : FL, FC, FR, RL, RR, LFE
594 swap(samples
[i
+1], samples
[i
+2]);
595 swap(samples
[i
+3], samples
[i
+5]);
596 swap(samples
[i
+4], samples
[i
+5]);
599 else if(oggInfo
->channels
== 7)
601 ALshort
*samples
= (ALshort
*)data
;
602 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=7)
604 // OpenAL : FL, FR, FC, LFE, RC, SL, SR
605 // Vorbis : FL, FC, FR, SL, SR, RC, LFE
606 swap(samples
[i
+1], samples
[i
+2]);
607 swap(samples
[i
+3], samples
[i
+6]);
608 swap(samples
[i
+4], samples
[i
+6]);
609 swap(samples
[i
+5], samples
[i
+6]);
612 else if(oggInfo
->channels
== 8)
614 ALshort
*samples
= (ALshort
*)data
;
615 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=8)
617 // OpenAL : FL, FR, FC, LFE, RL, RR, SL, SR
618 // Vorbis : FL, FC, FR, SL, SR, RL, RR, LFE
619 swap(samples
[i
+1], samples
[i
+2]);
620 swap(samples
[i
+3], samples
[i
+7]);
621 swap(samples
[i
+4], samples
[i
+5]);
622 swap(samples
[i
+5], samples
[i
+6]);
623 swap(samples
[i
+6], samples
[i
+7]);
629 virtual bool Rewind()
631 if(pov_pcm_seek(&oggFile
, 0) == 0)
634 SetError("Seek failed");
638 oggStream(std::istream
*_fstream
)
639 : alureStream(_fstream
), oggInfo(NULL
), oggBitstream(0), format(AL_NONE
)
641 if(!vorbisfile_handle
) return;
643 const ov_callbacks streamIO
= {
644 read
, seek
, close
, tell
647 if(pov_open_callbacks(this, &oggFile
, NULL
, 0, streamIO
) == 0)
649 oggInfo
= pov_info(&oggFile
, -1);
663 // libVorbisFile iostream callbacks
664 static int seek(void *user_data
, ogg_int64_t offset
, int whence
)
666 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
669 if(whence
== SEEK_CUR
)
670 stream
->seekg(offset
, std::ios_base::cur
);
671 else if(whence
== SEEK_SET
)
672 stream
->seekg(offset
, std::ios_base::beg
);
673 else if(whence
== SEEK_END
)
674 stream
->seekg(offset
, std::ios_base::end
);
678 return stream
->tellg();
681 static size_t read(void *ptr
, size_t size
, size_t nmemb
, void *user_data
)
683 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
686 stream
->read(static_cast<char*>(ptr
), nmemb
*size
);
687 size_t ret
= stream
->gcount();
691 static long tell(void *user_data
)
693 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
695 return stream
->tellg();
698 static int close(void*)
704 struct oggStream
: public nullStream
{
705 oggStream(std::istream
*){}
710 struct flacStream
: public alureStream
{
711 FLAC__StreamDecoder
*flacFile
;
717 std::vector
<ALubyte
> initialData
;
723 virtual bool IsValid()
724 { return flacFile
!= NULL
; }
726 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
729 *frequency
= samplerate
;
730 *blockalign
= blockAlign
;
734 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
740 if(initialData
.size() > 0)
742 size_t rem
= std::min(initialData
.size(), (size_t)bytes
);
743 memcpy(data
, &initialData
[0], rem
);
745 initialData
.erase(initialData
.begin(), initialData
.begin()+rem
);
748 while(outTotal
< bytes
)
750 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
751 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
758 virtual bool Rewind()
760 if(pFLAC__stream_decoder_seek_absolute(flacFile
, 0) != false)
766 SetError("Seek failed");
770 flacStream(std::istream
*_fstream
)
771 : alureStream(_fstream
), flacFile(NULL
), format(AL_NONE
), samplerate(0),
772 blockAlign(0), useFloat(AL_FALSE
)
774 if(!flac_handle
) return;
776 flacFile
= pFLAC__stream_decoder_new();
779 if(pFLAC__stream_decoder_init_stream(flacFile
, ReadCallback
, SeekCallback
, TellCallback
, LengthCallback
, EofCallback
, WriteCallback
, MetadataCallback
, ErrorCallback
, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK
)
787 pFLAC__stream_decoder_finish(flacFile
);
789 pFLAC__stream_decoder_delete(flacFile
);
794 virtual ~flacStream()
798 pFLAC__stream_decoder_finish(flacFile
);
799 pFLAC__stream_decoder_delete(flacFile
);
807 // We need to decode some data to be able to get the channel count, bit
808 // depth, and sample rate. It also ensures the file has FLAC data, as
809 // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
813 while(initialData
.size() == 0)
815 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
816 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
820 if(initialData
.size() > 0)
825 static FLAC__StreamDecoderWriteStatus
WriteCallback(const FLAC__StreamDecoder
*, const FLAC__Frame
*frame
, const FLAC__int32
*const buffer
[], void *client_data
)
827 flacStream
*self
= static_cast<flacStream
*>(client_data
);
828 ALubyte
*data
= self
->outBytes
+ self
->outTotal
;
831 if(self
->format
== AL_NONE
)
833 ALuint bps
= frame
->header
.bits_per_sample
;
834 if(bps
== 24 || bps
== 32)
836 self
->format
= GetSampleFormat(frame
->header
.channels
, 32, true);
837 if(self
->format
!= AL_NONE
)
839 self
->useFloat
= AL_TRUE
;
844 if(self
->format
== AL_NONE
)
845 self
->format
= GetSampleFormat(frame
->header
.channels
, bps
, false);
846 self
->blockAlign
= frame
->header
.channels
* bps
/8;
847 self
->samplerate
= frame
->header
.sample_rate
;
850 const ALboolean useFloat
= self
->useFloat
;
851 while(self
->outTotal
< self
->outLen
&& i
< frame
->header
.blocksize
)
853 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
855 if(frame
->header
.bits_per_sample
== 8)
856 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
857 else if(frame
->header
.bits_per_sample
== 16)
858 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
859 else if(frame
->header
.bits_per_sample
== 24)
862 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
863 buffer
[c
][i
]/(float)0x7FFFFF :
864 buffer
[c
][i
]/(float)0x800000);
866 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
868 else if(frame
->header
.bits_per_sample
== 32)
871 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
872 buffer
[c
][i
]/(float)0x7FFFFFFF :
873 buffer
[c
][i
]/(float)0x80000000u
);
875 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
878 self
->outTotal
+= self
->blockAlign
;
879 data
+= self
->blockAlign
;
883 if(i
< frame
->header
.blocksize
)
885 ALuint blocklen
= (frame
->header
.blocksize
-i
) *
887 ALuint start
= self
->initialData
.size();
889 self
->initialData
.resize(start
+blocklen
);
890 data
= &self
->initialData
[start
];
893 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
895 if(frame
->header
.bits_per_sample
== 8)
896 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
897 else if(frame
->header
.bits_per_sample
== 16)
898 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
899 else if(frame
->header
.bits_per_sample
== 24)
902 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
903 buffer
[c
][i
]/(float)0x7FFFFF :
904 buffer
[c
][i
]/(float)0x800000);
906 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
908 else if(frame
->header
.bits_per_sample
== 32)
911 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
912 buffer
[c
][i
]/(float)0x7FFFFFFF :
913 buffer
[c
][i
]/(float)0x80000000u
);
915 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
918 data
+= self
->blockAlign
;
920 } while(i
< frame
->header
.blocksize
);
923 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
925 static void MetadataCallback(const FLAC__StreamDecoder
*,const FLAC__StreamMetadata
*,void*)
928 static void ErrorCallback(const FLAC__StreamDecoder
*,FLAC__StreamDecoderErrorStatus
,void*)
932 static FLAC__StreamDecoderReadStatus
ReadCallback(const FLAC__StreamDecoder
*, FLAC__byte buffer
[], size_t *bytes
, void *client_data
)
934 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
938 return FLAC__STREAM_DECODER_READ_STATUS_ABORT
;
940 stream
->read(reinterpret_cast<char*>(buffer
), *bytes
);
941 *bytes
= stream
->gcount();
942 if(*bytes
== 0 && stream
->eof())
943 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
;
945 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
;
947 static FLAC__StreamDecoderSeekStatus
SeekCallback(const FLAC__StreamDecoder
*, FLAC__uint64 absolute_byte_offset
, void *client_data
)
949 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
952 if(!stream
->seekg(absolute_byte_offset
))
953 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
;
954 return FLAC__STREAM_DECODER_SEEK_STATUS_OK
;
956 static FLAC__StreamDecoderTellStatus
TellCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*absolute_byte_offset
, void *client_data
)
958 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
961 *absolute_byte_offset
= stream
->tellg();
962 return FLAC__STREAM_DECODER_TELL_STATUS_OK
;
964 static FLAC__StreamDecoderLengthStatus
LengthCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*stream_length
, void *client_data
)
966 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
969 std::streampos pos
= stream
->tellg();
970 if(stream
->seekg(0, std::ios_base::end
))
972 *stream_length
= stream
->tellg();
977 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
;
978 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK
;
980 static FLAC__bool
EofCallback(const FLAC__StreamDecoder
*, void *client_data
)
982 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
983 return (stream
->eof()) ? true : false;
987 struct flacStream
: public nullStream
{
988 flacStream(std::istream
*){}
994 struct mp3Stream
: public alureStream
{
995 mpg123_handle
*mp3File
;
1000 virtual bool IsValid()
1001 { return mp3File
!= NULL
; }
1003 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1006 *frequency
= samplerate
;
1007 *blockalign
= channels
*2;
1011 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1017 int ret
= pmpg123_read(mp3File
, data
, bytes
, &got
);
1023 if(ret
== MPG123_NEW_FORMAT
)
1027 pmpg123_getformat(mp3File
, &newrate
, &newchans
, &enc
);
1030 if(ret
== MPG123_NEED_MORE
)
1032 unsigned char data
[4096];
1033 fstream
->read((char*)data
, sizeof(data
));
1034 std::streamsize insize
= fstream
->gcount();
1035 if(insize
> 0 && pmpg123_feed(mp3File
, data
, insize
) == MPG123_OK
)
1044 virtual bool Rewind()
1047 std::istream::pos_type oldpos
= fstream
->tellg();
1050 mpg123_handle
*newFile
= pmpg123_new(NULL
, NULL
);
1051 if(pmpg123_open_feed(newFile
) == MPG123_OK
)
1053 unsigned char data
[4096];
1058 ALuint amt
, total
= 0;
1060 fstream
->read((char*)data
, sizeof(data
));
1061 amt
= fstream
->gcount();
1064 ret
= pmpg123_decode(newFile
, data
, amt
, NULL
, 0, NULL
);
1065 } while(ret
== MPG123_NEED_MORE
&& total
< 64*1024);
1067 if(ret
== MPG123_NEW_FORMAT
&&
1068 pmpg123_getformat(newFile
, &newrate
, &newchans
, &enc
) == MPG123_OK
)
1070 if(pmpg123_format_none(newFile
) == MPG123_OK
&&
1071 pmpg123_format(newFile
, samplerate
, channels
, MPG123_ENC_SIGNED_16
) == MPG123_OK
)
1074 pmpg123_delete(mp3File
);
1079 pmpg123_delete(newFile
);
1082 fstream
->seekg(oldpos
);
1083 SetError("Restart failed");
1087 mp3Stream(std::istream
*_fstream
)
1088 : alureStream(_fstream
), mp3File(NULL
), format(AL_NONE
)
1090 if(!mp123_handle
) return;
1092 mp3File
= pmpg123_new(NULL
, NULL
);
1093 if(pmpg123_open_feed(mp3File
) == MPG123_OK
)
1095 unsigned char data
[4096];
1098 ALuint amt
, total
= 0;
1100 fstream
->read((char*)data
, sizeof(data
));
1101 amt
= fstream
->gcount();
1104 ret
= pmpg123_decode(mp3File
, data
, amt
, NULL
, 0, NULL
);
1105 } while(ret
== MPG123_NEED_MORE
&& total
< 64*1024);
1107 if(ret
== MPG123_NEW_FORMAT
&&
1108 pmpg123_getformat(mp3File
, &samplerate
, &channels
, &enc
) == MPG123_OK
)
1110 format
= GetSampleFormat(channels
, 16, false);
1111 if(pmpg123_format_none(mp3File
) == MPG123_OK
&&
1112 pmpg123_format(mp3File
, samplerate
, channels
, MPG123_ENC_SIGNED_16
) == MPG123_OK
)
1119 pmpg123_delete(mp3File
);
1123 virtual ~mp3Stream()
1126 pmpg123_delete(mp3File
);
1131 struct mp3Stream
: public nullStream
{
1132 mp3Stream(std::istream
*){}
1138 struct dumbStream
: public alureStream
{
1139 DUMBFILE_SYSTEM vfs
;
1142 DUH_SIGRENDERER
*renderer
;
1143 std::vector
<sample_t
> sampleBuf
;
1148 virtual bool IsValid()
1149 { return renderer
!= NULL
; }
1151 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1153 if(format
== AL_NONE
)
1155 format
= GetSampleFormat(2, 32, true);
1156 if(format
== AL_NONE
)
1157 format
= AL_FORMAT_STEREO16
;
1160 *frequency
= samplerate
;
1161 *blockalign
= 2 * ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) :
1166 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1170 if(pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(renderer
)) == 0)
1173 ALuint sample_count
= bytes
/ ((format
==AL_FORMAT_STEREO16
) ?
1174 sizeof(ALshort
) : sizeof(ALfloat
));
1176 sampleBuf
.resize(sample_count
);
1177 sample_t
*samples
[] = {
1181 pdumb_silence(samples
[0], sample_count
);
1182 ret
= pduh_sigrenderer_generate_samples(renderer
, 1.0f
, 65536.0f
/samplerate
, sample_count
/2, samples
);
1184 if(format
== AL_FORMAT_STEREO16
)
1186 for(ALuint i
= 0;i
< ret
;i
++)
1187 ((ALshort
*)data
)[i
] = clamp(samples
[0][i
]>>8, -32768, 32767);
1191 for(ALuint i
= 0;i
< ret
;i
++)
1192 ((ALfloat
*)data
)[i
] = ((samples
[0][i
]>=0) ?
1193 samples
[0][i
]/(float)0x7FFFFF :
1194 samples
[0][i
]/(float)0x800000);
1196 ret
*= ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) : sizeof(ALfloat
));
1201 virtual bool Rewind()
1203 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
1206 SetError("Could start renderer");
1209 pduh_end_sigrenderer(renderer
);
1210 renderer
= newrenderer
;
1214 virtual bool SetOrder(ALuint order
)
1216 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, order
);
1219 SetError("Could not set order");
1222 pduh_end_sigrenderer(renderer
);
1223 renderer
= newrenderer
;
1229 dumbStream(std::istream
*_fstream
)
1230 : alureStream(_fstream
), dumbFile(NULL
), duh(NULL
), renderer(NULL
),
1231 lastOrder(0), format(AL_NONE
), samplerate(48000)
1233 if(!dumb_handle
) return;
1235 ALCdevice
*device
= alcGetContextsDevice(alcGetCurrentContext());
1237 alcGetIntegerv(device
, ALC_FREQUENCY
, 1, &samplerate
);
1239 DUH
* (*funcs
[])(DUMBFILE
*) = {
1249 vfs
.getc
= read_char
;
1253 for(size_t i
= 0;funcs
[i
];i
++)
1255 dumbFile
= pdumbfile_open_ex(this, &vfs
);
1258 duh
= funcs
[i
](dumbFile
);
1261 renderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
1264 pdumb_it_set_loop_callback(pduh_get_it_sigrenderer(renderer
), loop_cb
, this);
1272 pdumbfile_close(dumbFile
);
1280 virtual ~dumbStream()
1283 pduh_end_sigrenderer(renderer
);
1291 pdumbfile_close(dumbFile
);
1296 // DUMBFILE iostream callbacks
1297 static int skip(void *user_data
, long offset
)
1299 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1302 if(stream
->seekg(offset
, std::ios_base::cur
))
1307 static long read(char *ptr
, long size
, void *user_data
)
1309 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1312 stream
->read(ptr
, size
);
1313 return stream
->gcount();
1316 static int read_char(void *user_data
)
1318 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1322 stream
->read(reinterpret_cast<char*>(&ret
), 1);
1323 if(stream
->gcount() > 0)
1328 static int loop_cb(void *user_data
)
1330 dumbStream
*self
= static_cast<dumbStream
*>(user_data
);
1331 pdumb_it_sr_set_speed(pduh_get_it_sigrenderer(self
->renderer
), 0);
1336 struct dumbStream
: public nullStream
{
1337 dumbStream(std::istream
*){}
1342 template <typename T
>
1343 alureStream
*get_stream_decoder(const T
&fdata
)
1345 alureStream
*stream
;
1347 std::map
<ALint
,UserCallbacks
>::iterator i
= InstalledCallbacks
.begin();
1348 while(i
!= InstalledCallbacks
.end() && i
->first
< 0)
1350 stream
= new customStream(fdata
, i
->second
);
1351 if(stream
->IsValid())
1357 std::istream
*file
= new InStream(fdata
);
1360 stream
= new wavStream(file
);
1361 if(stream
->IsValid())
1366 file
->seekg(0, std::ios_base::beg
);
1367 stream
= new aiffStream(file
);
1368 if(stream
->IsValid())
1372 // Try libVorbisFile
1374 file
->seekg(0, std::ios_base::beg
);
1375 stream
= new oggStream(file
);
1376 if(stream
->IsValid())
1382 file
->seekg(0, std::ios_base::beg
);
1383 stream
= new flacStream(file
);
1384 if(stream
->IsValid())
1390 file
->seekg(0, std::ios_base::beg
);
1391 stream
= new dumbStream(file
);
1392 if(stream
->IsValid())
1398 file
->seekg(0, std::ios_base::beg
);
1399 stream
= new sndStream(file
);
1400 if(stream
->IsValid())
1406 file
->seekg(0, std::ios_base::beg
);
1407 stream
= new mp3Stream(file
);
1408 if(stream
->IsValid())
1412 SetError("Unsupported type");
1417 SetError("Failed to open file");
1421 while(i
!= InstalledCallbacks
.end())
1423 stream
= new customStream(fdata
, i
->second
);
1424 if(stream
->IsValid())
1430 return new nullStream
;
1433 alureStream
*create_stream(const char *fname
)
1434 { return get_stream_decoder(fname
); }
1435 alureStream
*create_stream(const MemDataInfo
&memData
)
1436 { return get_stream_decoder(memData
); }
1438 alureStream
*create_stream(ALvoid
*userdata
, ALenum format
, ALuint rate
, const UserCallbacks
&cb
)
1439 { return new customStream(userdata
, format
, rate
, cb
); }