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
41 typedef std::auto_ptr
<alureStream
>(*FactoryType
)(std::istream
*);
42 typedef std::vector
<FactoryType
> ListType
;
44 static const ListType
& GetList()
45 { return AddList(NULL
); }
49 static std::auto_ptr
<alureStream
> Factory(std::istream
*file
)
51 std::auto_ptr
<alureStream
> ret(new T(file
));
52 if(ret
->IsValid()) return ret
;
53 return std::auto_ptr
<alureStream
>();
56 static const ListType
& AddList(FactoryType func
)
58 static ListType FuncList
;
59 if(func
) FuncList
.push_back(func
);
64 struct DecoderDecl
: public Decoder
{
65 DecoderDecl() { AddList(Factory
<T
>); }
69 static inline ALuint
read_le32(std::istream
*file
)
72 if(!file
->read(reinterpret_cast<char*>(buffer
), 4)) return 0;
73 return buffer
[0] | (buffer
[1]<<8) | (buffer
[2]<<16) | (buffer
[3]<<24);
76 static inline ALushort
read_le16(std::istream
*file
)
79 if(!file
->read(reinterpret_cast<char*>(buffer
), 2)) return 0;
80 return buffer
[0] | (buffer
[1]<<8);
83 static inline ALuint
read_be32(std::istream
*file
)
86 if(!file
->read(reinterpret_cast<char*>(buffer
), 4)) return 0;
87 return (buffer
[0]<<24) | (buffer
[1]<<16) | (buffer
[2]<<8) | buffer
[3];
90 static inline ALushort
read_be16(std::istream
*file
)
93 if(!file
->read(reinterpret_cast<char*>(buffer
), 2)) return 0;
94 return (buffer
[0]<<8) | buffer
[1];
97 static inline ALuint
read_be80extended(std::istream
*file
)
100 if(!file
->read(reinterpret_cast<char*>(buffer
), 10)) return 0;
101 ALuint mantissa
, last
= 0;
102 ALubyte exp
= buffer
[1];
104 mantissa
= (buffer
[2]<<24) | (buffer
[3]<<16) | (buffer
[4]<<8) | buffer
[5];
110 if((last
&1)) mantissa
++;
115 struct nullStream
: public alureStream
{
116 virtual bool IsValid() { return false; }
117 virtual bool GetFormat(ALenum
*,ALuint
*,ALuint
*) { return false; }
118 virtual ALuint
GetData(ALubyte
*,ALuint
) { return 0; }
119 virtual bool Rewind() { return false; }
120 nullStream():alureStream(NULL
) {}
124 struct customStream
: public alureStream
{
133 virtual bool IsValid()
134 { return usrFile
!= NULL
; }
136 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
138 if(format
== AL_NONE
)
140 if(!cb
.get_fmt
|| !cb
.get_fmt(usrFile
, &format
, &samplerate
, &blockAlign
))
143 if(DetectBlockAlignment(format
) != blockAlign
)
147 *frequency
= samplerate
;
148 *blockalign
= blockAlign
;
152 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
153 { return cb
.decode(usrFile
, data
, bytes
); }
155 virtual bool Rewind()
157 if(cb
.rewind
&& cb
.rewind(usrFile
))
159 SetError("Rewind failed");
163 customStream(const char *fname
, const UserCallbacks
&callbacks
)
164 : alureStream(NULL
), usrFile(NULL
), format(0), samplerate(0),
165 blockAlign(0), cb(callbacks
)
166 { if(cb
.open_file
) usrFile
= cb
.open_file(fname
); }
168 customStream(const MemDataInfo
&memData
, const UserCallbacks
&callbacks
)
169 : alureStream(NULL
), usrFile(NULL
), format(0), samplerate(0),
170 blockAlign(0), memInfo(memData
), cb(callbacks
)
171 { if(cb
.open_mem
) usrFile
= cb
.open_mem(memInfo
.Data
, memInfo
.Length
); }
173 customStream(void *userdata
, ALenum fmt
, ALuint srate
, const UserCallbacks
&callbacks
)
174 : alureStream(NULL
), usrFile(userdata
), format(fmt
), samplerate(srate
),
175 blockAlign(DetectBlockAlignment(format
)), cb(callbacks
)
178 virtual ~customStream()
180 if(cb
.close
&& usrFile
)
187 struct wavStream
: public alureStream
{
196 virtual bool IsValid()
197 { return (dataStart
> 0 && format
!= AL_NONE
); }
199 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
202 *frequency
= samplerate
;
203 *blockalign
= blockAlign
;
207 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
209 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
210 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
212 std::streamsize got
= fstream
->gcount();
213 got
-= got
%blockAlign
;
216 if(BigEndian
&& sampleSize
== 16)
218 for(std::streamsize i
= 0;i
< got
;i
+=2)
219 swap(data
[i
], data
[i
+1]);
221 else if(BigEndian
&& sampleSize
== 32)
223 for(std::streamsize i
= 0;i
< got
;i
+=4)
225 swap(data
[i
+0], data
[i
+3]);
226 swap(data
[i
+1], data
[i
+2]);
229 else if(BigEndian
&& sampleSize
== 64)
231 for(std::streamsize i
= 0;i
< got
;i
+=8)
233 swap(data
[i
+0], data
[i
+7]);
234 swap(data
[i
+1], data
[i
+6]);
235 swap(data
[i
+2], data
[i
+5]);
236 swap(data
[i
+3], data
[i
+4]);
243 virtual bool Rewind()
246 if(fstream
->seekg(dataStart
))
252 SetError("Seek failed");
256 wavStream(std::istream
*_fstream
)
257 : alureStream(_fstream
), format(0), dataStart(0)
262 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
263 memcmp(buffer
, "RIFF", 4) != 0 || memcmp(buffer
+8, "WAVE", 4) != 0)
266 while(!dataStart
|| format
== AL_NONE
)
269 if(!fstream
->read(tag
, 4))
272 /* read chunk length */
273 length
= read_le32(fstream
);
275 if(memcmp(tag
, "fmt ", 4) == 0 && length
>= 16)
277 /* Data type (should be 1 for PCM data, 3 for float PCM data,
278 * and 17 for IMA4 data) */
279 int type
= read_le16(fstream
);
280 if(type
!= 0x0001 && type
!= 0x0003 && type
!= 0x0011)
283 /* mono or stereo data */
284 int channels
= read_le16(fstream
);
286 /* sample frequency */
287 samplerate
= read_le32(fstream
);
289 /* skip average bytes per second */
292 /* bytes per block */
293 blockAlign
= read_le16(fstream
);
297 /* bits per sample */
298 sampleSize
= read_le16(fstream
);
302 /* Look for any extra data and try to find the format */
306 extrabytes
= read_le16(fstream
);
309 extrabytes
= std::min(extrabytes
, length
);
312 format
= GetSampleFormat(channels
, sampleSize
, false);
313 else if(type
== 0x0003)
314 format
= GetSampleFormat(channels
, sampleSize
, true);
315 else if(type
== 0x0011 && extrabytes
>= 2)
317 int samples
= read_le16(fstream
);
320 /* AL_EXT_IMA4 only supports 36 bytes-per-channel block
321 * alignment, which has 65 uncompressed sample frames */
322 if(blockAlign
== 36*channels
&& samples
== 65*channels
&&
323 alIsExtensionPresent("AL_EXT_IMA4"))
326 format
= AL_FORMAT_MONO_IMA4
;
327 else if(channels
== 2)
328 format
= AL_FORMAT_STEREO_IMA4
;
332 else if(memcmp(tag
, "data", 4) == 0)
334 dataStart
= fstream
->tellg();
335 dataLen
= remLen
= length
;
338 fstream
->seekg(length
, std::ios_base::cur
);
341 if(dataStart
> 0 && format
!= AL_NONE
)
342 fstream
->seekg(dataStart
);
348 static DecoderDecl
<wavStream
> wavStream_decoder
;
351 struct aiffStream
: public alureStream
{
360 virtual bool IsValid()
361 { return (dataStart
> 0 && format
!= AL_NONE
); }
363 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
366 *frequency
= samplerate
;
367 *blockalign
= blockAlign
;
371 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
373 std::streamsize rem
= ((remLen
>= bytes
) ? bytes
: remLen
) / blockAlign
;
374 fstream
->read(reinterpret_cast<char*>(data
), rem
*blockAlign
);
376 std::streamsize got
= fstream
->gcount();
377 got
-= got
%blockAlign
;
384 for(std::streamsize i
= 0;i
< got
;i
+=2)
385 swap(data
[i
], data
[i
+1]);
387 else if(sampleSize
== 4)
389 for(std::streamsize i
= 0;i
< got
;i
+=4)
391 swap(data
[i
+0], data
[i
+3]);
392 swap(data
[i
+1], data
[i
+2]);
400 virtual bool Rewind()
403 if(fstream
->seekg(dataStart
))
409 SetError("Seek failed");
413 aiffStream(std::istream
*_fstream
)
414 : alureStream(_fstream
), format(0), dataStart(0)
419 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12) ||
420 memcmp(buffer
, "FORM", 4) != 0 || memcmp(buffer
+8, "AIFF", 4) != 0)
423 while(!dataStart
|| format
== AL_NONE
)
426 if(!fstream
->read(tag
, 4))
429 /* read chunk length */
430 length
= read_be32(fstream
);
432 if(memcmp(tag
, "COMM", 4) == 0 && length
>= 18)
434 /* mono or stereo data */
435 int channels
= read_be16(fstream
);
437 /* number of sample frames */
440 /* bits per sample */
441 sampleSize
= read_be16(fstream
) / 8;
443 /* sample frequency */
444 samplerate
= read_be80extended(fstream
);
446 /* block alignment */
447 blockAlign
= channels
* sampleSize
;
449 format
= GetSampleFormat(channels
, sampleSize
*8, false);
453 else if(memcmp(tag
, "SSND", 4) == 0)
455 dataStart
= fstream
->tellg();
457 dataLen
= remLen
= length
- 8;
460 fstream
->seekg(length
, std::ios_base::cur
);
463 if(dataStart
> 0 && format
!= AL_NONE
)
464 fstream
->seekg(dataStart
);
467 virtual ~aiffStream()
470 static DecoderDecl
<aiffStream
> aiffStream_decoder
;
472 #ifdef HAS_VORBISFILE
473 struct oggStream
: public alureStream
{
474 OggVorbis_File oggFile
;
475 vorbis_info
*oggInfo
;
479 virtual bool IsValid()
480 { return oggInfo
!= NULL
; }
482 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
484 if(format
== AL_NONE
)
485 format
= GetSampleFormat(oggInfo
->channels
, 16, false);
487 *frequency
= oggInfo
->rate
;
488 *blockalign
= oggInfo
->channels
*2;
492 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
497 int res
= pov_read(&oggFile
, (char*)&data
[got
], bytes
, BigEndian
?1:0, 2, 1, &oggBitstream
);
503 // 1, 2, and 4 channel files decode into the same channel order as
504 // OpenAL, however 6(5.1), 7(6.1), and 8(7.1) channel files need to be
506 if(oggInfo
->channels
== 6)
508 ALshort
*samples
= (ALshort
*)data
;
509 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=6)
511 // OpenAL : FL, FR, FC, LFE, RL, RR
512 // Vorbis : FL, FC, FR, RL, RR, LFE
513 swap(samples
[i
+1], samples
[i
+2]);
514 swap(samples
[i
+3], samples
[i
+5]);
515 swap(samples
[i
+4], samples
[i
+5]);
518 else if(oggInfo
->channels
== 7)
520 ALshort
*samples
= (ALshort
*)data
;
521 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=7)
523 // OpenAL : FL, FR, FC, LFE, RC, SL, SR
524 // Vorbis : FL, FC, FR, SL, SR, RC, LFE
525 swap(samples
[i
+1], samples
[i
+2]);
526 swap(samples
[i
+3], samples
[i
+6]);
527 swap(samples
[i
+4], samples
[i
+6]);
528 swap(samples
[i
+5], samples
[i
+6]);
531 else if(oggInfo
->channels
== 8)
533 ALshort
*samples
= (ALshort
*)data
;
534 for(ALuint i
= 0;i
< got
/sizeof(ALshort
);i
+=8)
536 // OpenAL : FL, FR, FC, LFE, RL, RR, SL, SR
537 // Vorbis : FL, FC, FR, SL, SR, RL, RR, LFE
538 swap(samples
[i
+1], samples
[i
+2]);
539 swap(samples
[i
+3], samples
[i
+7]);
540 swap(samples
[i
+4], samples
[i
+5]);
541 swap(samples
[i
+5], samples
[i
+6]);
542 swap(samples
[i
+6], samples
[i
+7]);
548 virtual bool Rewind()
550 if(pov_pcm_seek(&oggFile
, 0) == 0)
553 SetError("Seek failed");
557 oggStream(std::istream
*_fstream
)
558 : alureStream(_fstream
), oggInfo(NULL
), oggBitstream(0), format(AL_NONE
)
560 if(!vorbisfile_handle
) return;
562 const ov_callbacks streamIO
= {
563 read
, seek
, close
, tell
566 if(pov_open_callbacks(this, &oggFile
, NULL
, 0, streamIO
) == 0)
568 oggInfo
= pov_info(&oggFile
, -1);
582 // libVorbisFile iostream callbacks
583 static int seek(void *user_data
, ogg_int64_t offset
, int whence
)
585 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
588 if(whence
== SEEK_CUR
)
589 stream
->seekg(offset
, std::ios_base::cur
);
590 else if(whence
== SEEK_SET
)
591 stream
->seekg(offset
, std::ios_base::beg
);
592 else if(whence
== SEEK_END
)
593 stream
->seekg(offset
, std::ios_base::end
);
597 return stream
->tellg();
600 static size_t read(void *ptr
, size_t size
, size_t nmemb
, void *user_data
)
602 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
605 stream
->read(static_cast<char*>(ptr
), nmemb
*size
);
606 size_t ret
= stream
->gcount();
610 static long tell(void *user_data
)
612 std::istream
*stream
= static_cast<oggStream
*>(user_data
)->fstream
;
614 return stream
->tellg();
617 static int close(void*)
622 static DecoderDecl
<oggStream
> oggStream_decoder
;
626 struct flacStream
: public alureStream
{
627 FLAC__StreamDecoder
*flacFile
;
633 std::vector
<ALubyte
> initialData
;
639 virtual bool IsValid()
640 { return flacFile
!= NULL
; }
642 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
645 *frequency
= samplerate
;
646 *blockalign
= blockAlign
;
650 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
656 if(initialData
.size() > 0)
658 size_t rem
= std::min(initialData
.size(), (size_t)bytes
);
659 memcpy(data
, &initialData
[0], rem
);
661 initialData
.erase(initialData
.begin(), initialData
.begin()+rem
);
664 while(outTotal
< bytes
)
666 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
667 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
674 virtual bool Rewind()
676 if(pFLAC__stream_decoder_seek_absolute(flacFile
, 0) != false)
682 SetError("Seek failed");
686 flacStream(std::istream
*_fstream
)
687 : alureStream(_fstream
), flacFile(NULL
), format(AL_NONE
), samplerate(0),
688 blockAlign(0), useFloat(AL_FALSE
)
690 if(!flac_handle
) return;
692 flacFile
= pFLAC__stream_decoder_new();
695 if(pFLAC__stream_decoder_init_stream(flacFile
, ReadCallback
, SeekCallback
, TellCallback
, LengthCallback
, EofCallback
, WriteCallback
, MetadataCallback
, ErrorCallback
, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK
)
703 pFLAC__stream_decoder_finish(flacFile
);
705 pFLAC__stream_decoder_delete(flacFile
);
710 virtual ~flacStream()
714 pFLAC__stream_decoder_finish(flacFile
);
715 pFLAC__stream_decoder_delete(flacFile
);
723 // We need to decode some data to be able to get the channel count, bit
724 // depth, and sample rate. It also ensures the file has FLAC data, as
725 // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
729 while(initialData
.size() == 0)
731 if(pFLAC__stream_decoder_process_single(flacFile
) == false ||
732 pFLAC__stream_decoder_get_state(flacFile
) == FLAC__STREAM_DECODER_END_OF_STREAM
)
736 if(initialData
.size() > 0)
741 static FLAC__StreamDecoderWriteStatus
WriteCallback(const FLAC__StreamDecoder
*, const FLAC__Frame
*frame
, const FLAC__int32
*const buffer
[], void *client_data
)
743 flacStream
*self
= static_cast<flacStream
*>(client_data
);
744 ALubyte
*data
= self
->outBytes
+ self
->outTotal
;
747 if(self
->format
== AL_NONE
)
749 ALuint bps
= frame
->header
.bits_per_sample
;
750 if(bps
== 24 || bps
== 32)
752 self
->format
= GetSampleFormat(frame
->header
.channels
, 32, true);
753 if(self
->format
!= AL_NONE
)
755 self
->useFloat
= AL_TRUE
;
760 if(self
->format
== AL_NONE
)
761 self
->format
= GetSampleFormat(frame
->header
.channels
, bps
, false);
762 self
->blockAlign
= frame
->header
.channels
* bps
/8;
763 self
->samplerate
= frame
->header
.sample_rate
;
766 const ALboolean useFloat
= self
->useFloat
;
767 while(self
->outTotal
< self
->outLen
&& i
< frame
->header
.blocksize
)
769 for(ALuint c
= 0;c
< frame
->header
.channels
;c
++)
771 if(frame
->header
.bits_per_sample
== 8)
772 ((ALubyte
*)data
)[c
] = buffer
[c
][i
]+128;
773 else if(frame
->header
.bits_per_sample
== 16)
774 ((ALshort
*)data
)[c
] = buffer
[c
][i
];
775 else if(frame
->header
.bits_per_sample
== 24)
778 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
779 buffer
[c
][i
]/(float)0x7FFFFF :
780 buffer
[c
][i
]/(float)0x800000);
782 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>8;
784 else if(frame
->header
.bits_per_sample
== 32)
787 ((ALfloat
*)data
)[c
] = ((buffer
[c
][i
]>=0) ?
788 buffer
[c
][i
]/(float)0x7FFFFFFF :
789 buffer
[c
][i
]/(float)0x80000000u
);
791 ((ALshort
*)data
)[c
] = buffer
[c
][i
]>>16;
794 self
->outTotal
+= self
->blockAlign
;
795 data
+= self
->blockAlign
;
799 if(i
< frame
->header
.blocksize
)
801 ALuint blocklen
= (frame
->header
.blocksize
-i
) *
803 ALuint start
= self
->initialData
.size();
805 self
->initialData
.resize(start
+blocklen
);
806 data
= &self
->initialData
[start
];
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 data
+= self
->blockAlign
;
836 } while(i
< frame
->header
.blocksize
);
839 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
841 static void MetadataCallback(const FLAC__StreamDecoder
*,const FLAC__StreamMetadata
*,void*)
844 static void ErrorCallback(const FLAC__StreamDecoder
*,FLAC__StreamDecoderErrorStatus
,void*)
848 static FLAC__StreamDecoderReadStatus
ReadCallback(const FLAC__StreamDecoder
*, FLAC__byte buffer
[], size_t *bytes
, void *client_data
)
850 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
854 return FLAC__STREAM_DECODER_READ_STATUS_ABORT
;
856 stream
->read(reinterpret_cast<char*>(buffer
), *bytes
);
857 *bytes
= stream
->gcount();
858 if(*bytes
== 0 && stream
->eof())
859 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
;
861 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE
;
863 static FLAC__StreamDecoderSeekStatus
SeekCallback(const FLAC__StreamDecoder
*, FLAC__uint64 absolute_byte_offset
, void *client_data
)
865 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
868 if(!stream
->seekg(absolute_byte_offset
))
869 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR
;
870 return FLAC__STREAM_DECODER_SEEK_STATUS_OK
;
872 static FLAC__StreamDecoderTellStatus
TellCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*absolute_byte_offset
, void *client_data
)
874 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
877 *absolute_byte_offset
= stream
->tellg();
878 return FLAC__STREAM_DECODER_TELL_STATUS_OK
;
880 static FLAC__StreamDecoderLengthStatus
LengthCallback(const FLAC__StreamDecoder
*, FLAC__uint64
*stream_length
, void *client_data
)
882 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
885 std::streampos pos
= stream
->tellg();
886 if(stream
->seekg(0, std::ios_base::end
))
888 *stream_length
= stream
->tellg();
893 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR
;
894 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK
;
896 static FLAC__bool
EofCallback(const FLAC__StreamDecoder
*, void *client_data
)
898 std::istream
*stream
= static_cast<flacStream
*>(client_data
)->fstream
;
899 return (stream
->eof()) ? true : false;
902 static DecoderDecl
<flacStream
> flacStream_decoder
;
905 #ifdef HAS_FLUIDSYNTH
906 struct fluidStream
: public alureStream
{
908 static const ALubyte MIDI_CHANNEL_MASK
= 0x0F;
909 static const ALubyte MIDI_EVENT_MASK
= 0xF0;
911 static const ALubyte MIDI_NOTEOFF
= 0x80; // + note + velocity
912 static const ALubyte MIDI_NOTEON
= 0x90; // + note + velocity
913 static const ALubyte MIDI_POLYPRESS
= 0xA0; // + pressure (2 bytes)
914 static const ALubyte MIDI_CTRLCHANGE
= 0xB0; // + ctrl + value
915 static const ALubyte MIDI_PRGMCHANGE
= 0xC0; // + new patch
916 static const ALubyte MIDI_CHANPRESS
= 0xD0; // + pressure (1 byte)
917 static const ALubyte MIDI_PITCHBEND
= 0xE0; // + pitch bend (2 bytes)
918 static const ALubyte MIDI_SPECIAL
= 0xF0; // Special event
920 static const ALubyte MIDI_SYSEX
= 0xF0; // SysEx begin
921 static const ALubyte MIDI_SYSEXEND
= 0xF7; // SysEx end
922 static const ALubyte MIDI_SONGPOS
= 0xF2; // Song position
923 static const ALubyte MIDI_SONGSEL
= 0xF3; // Song select
924 static const ALubyte MIDI_META
= 0xFF; // Meta event begin
926 static const ALubyte MIDI_META_EOT
= 0x2F; // End-of-track
927 static const ALubyte MIDI_META_TEMPO
= 0x51; // Tempo change
930 std::vector
<ALubyte
> data
;
933 ALdouble SamplesLeft
;
935 MidiTrack() : Offset(0), LastEvent(0), SamplesLeft(0.)
937 MidiTrack(const MidiTrack
&rhs
)
938 : data(rhs
.data
), Offset(rhs
.Offset
), LastEvent(rhs
.LastEvent
),
939 SamplesLeft(rhs
.SamplesLeft
)
949 const MidiTrack
& operator=(const MidiTrack
&rhs
)
953 LastEvent
= rhs
.LastEvent
;
954 SamplesLeft
= rhs
.SamplesLeft
;
958 unsigned long ReadVarLen()
960 if(Offset
>= data
.size())
963 unsigned long len
= data
[Offset
]&0x7F;
964 while((data
[Offset
]&0x80))
966 if(++Offset
>= data
.size())
968 len
= (len
<<7) | (data
[Offset
]&0x7F);
977 std::vector
<MidiTrack
> Tracks
;
981 ALdouble samplesPerTick
;
983 fluid_settings_t
*fluidSettings
;
984 fluid_synth_t
*fluidSynth
;
988 virtual bool IsValid()
989 { return fluidSynth
!= NULL
; }
991 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
993 if(format
== AL_NONE
)
995 format
= GetSampleFormat(2, 32, true);
996 if(format
== AL_NONE
)
997 format
= AL_FORMAT_STEREO16
;
1000 *frequency
= sampleRate
;
1001 *blockalign
= 2 * ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) :
1006 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1010 if(format
== AL_FORMAT_STEREO16
)
1012 ALshort
*ptr
= reinterpret_cast<ALshort
*>(data
);
1013 ret
= FillBuffer(ptr
, bytes
/2/sizeof(ALshort
));
1014 ret
*= 2 * sizeof(ALshort
);
1018 ALfloat
*ptr
= reinterpret_cast<ALfloat
*>(data
);
1019 ret
= FillBuffer(ptr
, bytes
/2/sizeof(ALfloat
));
1020 ret
*= 2 * sizeof(ALfloat
);
1026 virtual bool Rewind()
1028 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(), end
= Tracks
.end();i
!= end
;i
++)
1031 unsigned long val
= i
->ReadVarLen();
1032 i
->SamplesLeft
+= val
* samplesPerTick
;
1034 pfluid_synth_program_reset(fluidSynth
);
1035 UpdateTempo(500000);
1039 virtual bool SetPatchset(const char *sfont
)
1041 int newid
= pfluid_synth_sfload(fluidSynth
, sfont
, true);
1042 if(newid
== FLUID_FAILED
)
1044 SetError("Failed to load soundfont");
1048 if(fontID
!= FLUID_FAILED
)
1049 pfluid_synth_sfunload(fluidSynth
, fontID
, true);
1055 fluidStream(std::istream
*_fstream
)
1056 : alureStream(_fstream
), Divisions(100),
1057 format(AL_NONE
), sampleRate(48000), samplesPerTick(1.),
1058 fluidSettings(NULL
), fluidSynth(NULL
), fontID(FLUID_FAILED
)
1060 if(!fsynth_handle
) return;
1062 ALCdevice
*device
= alcGetContextsDevice(alcGetCurrentContext());
1064 alcGetIntegerv(device
, ALC_FREQUENCY
, 1, &sampleRate
);
1067 if(!fstream
->read(hdr
, 4))
1070 if(memcmp(hdr
, "MThd", 4) == 0)
1072 ALuint len
= read_be32(fstream
);
1076 int type
= read_be16(fstream
);
1077 if(type
!= 0 && type
!= 1)
1080 ALuint numtracks
= read_be16(fstream
);
1082 Divisions
= read_be16(fstream
);
1083 UpdateTempo(500000);
1085 Tracks
.resize(numtracks
);
1086 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(), end
= Tracks
.end();i
!= end
;i
++)
1088 if(!fstream
->read(hdr
, 4) || memcmp(hdr
, "MTrk", 4) != 0)
1091 ALuint len
= read_be32(fstream
);
1092 i
->data
.resize(len
);
1093 if(!fstream
->read(reinterpret_cast<char*>(&i
->data
[0]), len
))
1096 unsigned long val
= i
->ReadVarLen();
1097 i
->SamplesLeft
+= val
* samplesPerTick
;
1103 virtual ~fluidStream()
1105 if(fontID
!= FLUID_FAILED
)
1106 pfluid_synth_sfunload(fluidSynth
, fontID
, true);
1107 fontID
= FLUID_FAILED
;
1109 if(fluidSynth
!= NULL
)
1110 pdelete_fluid_synth(fluidSynth
);
1113 if(fluidSettings
!= NULL
)
1114 pdelete_fluid_settings(fluidSettings
);
1115 fluidSettings
= NULL
;
1119 template<typename T
>
1120 ALuint
FillBuffer(T
*Buffer
, ALuint BufferSamples
)
1122 ALuint SamplesInBuffer
= 0;
1123 while(SamplesInBuffer
< BufferSamples
)
1125 // Check if any tracks are still playing and how many samples are waiting to render
1126 size_t TracksPlaying
= 0;
1127 ALuint SamplesToDo
= BufferSamples
- SamplesInBuffer
;
1128 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(),
1129 end
= Tracks
.end();i
!= end
;i
++)
1131 if(i
->Offset
< i
->data
.size())
1133 SamplesToDo
= std::min
<ALuint
>(SamplesToDo
, i
->SamplesLeft
);
1137 if(TracksPlaying
== 0)
1140 if(SamplesToDo
== 0)
1147 WriteSamples(SamplesToDo
, Buffer
);
1148 Buffer
+= SamplesToDo
*2;
1149 SamplesInBuffer
+= SamplesToDo
;
1151 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(),
1152 end
= Tracks
.end();i
!= end
;i
++)
1154 if(i
->Offset
< i
->data
.size())
1155 i
->SamplesLeft
-= SamplesToDo
;
1159 return SamplesInBuffer
;
1162 void WriteSamples(ALuint count
, short *buffer
)
1163 { pfluid_synth_write_s16(fluidSynth
, count
, buffer
, 0, 2, buffer
, 1, 2); }
1164 void WriteSamples(ALuint count
, float *buffer
)
1165 { pfluid_synth_write_float(fluidSynth
, count
, buffer
, 0, 2, buffer
, 1, 2); }
1169 ALuint newtempo
= 0;
1171 // Process more events
1172 std::vector
<MidiTrack
>::iterator i
=Tracks
.begin(), end
=Tracks
.end();
1175 if(i
->Offset
>= i
->data
.size() || i
->SamplesLeft
>= 1.)
1181 if(i
->data
.size() - i
->Offset
< 3)
1183 i
->Offset
= i
->data
.size();
1188 ALubyte event
= i
->data
[i
->Offset
++];
1189 ALubyte parm1
, parm2
;
1192 event
= i
->LastEvent
;
1195 if((event
&MIDI_EVENT_MASK
) != MIDI_SPECIAL
)
1196 i
->LastEvent
= event
;
1197 parm1
= i
->data
[i
->Offset
];
1198 parm2
= i
->data
[i
->Offset
+1];
1200 int channel
= event
&MIDI_CHANNEL_MASK
;
1201 switch(event
&MIDI_EVENT_MASK
)
1204 pfluid_synth_noteoff(fluidSynth
, channel
, parm1
);
1208 pfluid_synth_noteon(fluidSynth
, channel
, parm1
, parm2
);
1211 case MIDI_POLYPRESS
:
1215 case MIDI_CTRLCHANGE
:
1216 pfluid_synth_cc(fluidSynth
, channel
, parm1
, parm2
);
1219 case MIDI_PRGMCHANGE
:
1220 pfluid_synth_program_change(fluidSynth
, channel
, parm1
);
1224 case MIDI_CHANPRESS
:
1225 pfluid_synth_channel_pressure(fluidSynth
, channel
, parm1
);
1229 case MIDI_PITCHBEND
:
1230 pfluid_synth_pitch_bend(fluidSynth
, channel
, (parm1
&0x7F) | ((parm2
&0x7F)<<7));
1239 unsigned long len
= i
->ReadVarLen();
1240 if(i
->data
.size() - i
->Offset
< len
)
1242 i
->Offset
= i
->data
.size();
1246 if(len
> 1 && i
->data
[len
-1] == MIDI_SYSEXEND
)
1248 char *data
= reinterpret_cast<char*>(&i
->data
[i
->Offset
]);
1249 pfluid_synth_sysex(fluidSynth
, data
, len
-1, NULL
, NULL
, NULL
, false);
1256 unsigned long len
= i
->ReadVarLen();
1257 if(i
->data
.size() - i
->Offset
< len
)
1259 i
->Offset
= i
->data
.size();
1276 ALubyte metatype
= i
->data
[i
->Offset
++];
1277 unsigned long val
= i
->ReadVarLen();
1279 if(i
->data
.size() - i
->Offset
< val
)
1281 i
->Offset
= i
->data
.size();
1285 if(metatype
== MIDI_META_EOT
)
1287 i
->Offset
= i
->data
.size();
1291 if(metatype
== MIDI_META_TEMPO
&& val
>= 3)
1293 newtempo
= (i
->data
[i
->Offset
] << 16) |
1294 (i
->data
[i
->Offset
+1] << 8) |
1295 (i
->data
[i
->Offset
+2]);
1303 /* The rest of the special events don't have any
1310 /* Shouldn't ever get to here */
1314 unsigned long val
= i
->ReadVarLen();
1315 i
->SamplesLeft
+= val
* samplesPerTick
;
1318 UpdateTempo(newtempo
);
1321 void UpdateTempo(ALuint tempo
)
1323 ALdouble sampletickrate
= sampleRate
/ (1000000. / tempo
) / Divisions
;
1325 for(std::vector
<MidiTrack
>::iterator i
= Tracks
.begin(),
1326 end
= Tracks
.end();i
!= end
;i
++)
1328 if(i
->Offset
>= i
->data
.size())
1330 i
->SamplesLeft
= i
->SamplesLeft
/ samplesPerTick
* sampletickrate
;
1332 samplesPerTick
= sampletickrate
;
1337 fluidSettings
= pnew_fluid_settings();
1340 pfluid_settings_setnum(fluidSettings
, "synth.gain", 0.5);
1341 pfluid_settings_setstr(fluidSettings
, "synth.reverb.active", "yes");
1342 pfluid_settings_setstr(fluidSettings
, "synth.chorus.active", "yes");
1343 pfluid_settings_setint(fluidSettings
, "synth.polyphony", 256);
1344 pfluid_settings_setnum(fluidSettings
, "synth.sample-rate", (double)sampleRate
);
1346 fluidSynth
= pnew_fluid_synth(fluidSettings
);
1349 const char *soundfont
= getenv("FLUID_SOUNDFONT");
1350 if(soundfont
&& soundfont
[0])
1351 fontID
= pfluid_synth_sfload(fluidSynth
, soundfont
, true);
1356 static DecoderDecl
<fluidStream
> fluidStream_decoder
;
1360 struct sndStream
: public alureStream
{
1365 virtual bool IsValid()
1366 { return sndFile
!= NULL
; }
1368 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1370 if(format
== AL_NONE
)
1371 format
= GetSampleFormat(sndInfo
.channels
, 16, false);
1373 *frequency
= sndInfo
.samplerate
;
1374 *blockalign
= sndInfo
.channels
*2;
1378 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1380 const ALuint frameSize
= 2*sndInfo
.channels
;
1381 return psf_readf_short(sndFile
, (short*)data
, bytes
/frameSize
) * frameSize
;
1384 virtual bool Rewind()
1386 if(psf_seek(sndFile
, 0, SEEK_SET
) != -1)
1389 SetError("Seek failed");
1393 sndStream(std::istream
*_fstream
)
1394 : alureStream(_fstream
), sndFile(NULL
), format(AL_NONE
)
1396 memset(&sndInfo
, 0, sizeof(sndInfo
));
1398 if(!sndfile_handle
) return;
1400 static SF_VIRTUAL_IO streamIO
= {
1404 sndFile
= psf_open_virtual(&streamIO
, SFM_READ
, &sndInfo
, this);
1407 virtual ~sndStream()
1415 // libSndFile iostream callbacks
1416 static sf_count_t
get_filelen(void *user_data
)
1418 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
1421 std::streampos len
= -1;
1422 std::streampos pos
= stream
->tellg();
1423 if(stream
->seekg(0, std::ios_base::end
))
1425 len
= stream
->tellg();
1432 static sf_count_t
seek(sf_count_t offset
, int whence
, void *user_data
)
1434 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
1437 if(whence
== SEEK_CUR
)
1438 stream
->seekg(offset
, std::ios_base::cur
);
1439 else if(whence
== SEEK_SET
)
1440 stream
->seekg(offset
, std::ios_base::beg
);
1441 else if(whence
== SEEK_END
)
1442 stream
->seekg(offset
, std::ios_base::end
);
1446 return stream
->tellg();
1449 static sf_count_t
read(void *ptr
, sf_count_t count
, void *user_data
)
1451 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
1453 stream
->read(static_cast<char*>(ptr
), count
);
1454 return stream
->gcount();
1457 static sf_count_t
write(const void*, sf_count_t
, void*)
1460 static sf_count_t
tell(void *user_data
)
1462 std::istream
*stream
= static_cast<sndStream
*>(user_data
)->fstream
;
1464 return stream
->tellg();
1467 static DecoderDecl
<sndStream
> sndStream_decoder
;
1471 struct dumbStream
: public alureStream
{
1472 DUMBFILE_SYSTEM vfs
;
1475 DUH_SIGRENDERER
*renderer
;
1476 std::vector
<sample_t
> sampleBuf
;
1481 virtual bool IsValid()
1482 { return renderer
!= NULL
; }
1484 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1486 if(format
== AL_NONE
)
1488 format
= GetSampleFormat(2, 32, true);
1489 if(format
== AL_NONE
)
1490 format
= AL_FORMAT_STEREO16
;
1493 *frequency
= samplerate
;
1494 *blockalign
= 2 * ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) :
1499 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1503 if(pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(renderer
)) == 0)
1506 ALuint sample_count
= bytes
/ ((format
==AL_FORMAT_STEREO16
) ?
1507 sizeof(ALshort
) : sizeof(ALfloat
));
1509 sampleBuf
.resize(sample_count
);
1510 sample_t
*samples
[] = {
1514 pdumb_silence(samples
[0], sample_count
);
1515 ret
= pduh_sigrenderer_generate_samples(renderer
, 1.0f
, 65536.0f
/samplerate
, sample_count
/2, samples
);
1517 if(format
== AL_FORMAT_STEREO16
)
1519 for(ALuint i
= 0;i
< ret
;i
++)
1520 ((ALshort
*)data
)[i
] = clamp(samples
[0][i
]>>8, -32768, 32767);
1524 for(ALuint i
= 0;i
< ret
;i
++)
1525 ((ALfloat
*)data
)[i
] = ((samples
[0][i
]>=0) ?
1526 samples
[0][i
]/(float)0x7FFFFF :
1527 samples
[0][i
]/(float)0x800000);
1529 ret
*= ((format
==AL_FORMAT_STEREO16
) ? sizeof(ALshort
) : sizeof(ALfloat
));
1534 virtual bool Rewind()
1536 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
1539 SetError("Could not start renderer");
1542 pduh_end_sigrenderer(renderer
);
1543 renderer
= newrenderer
;
1547 virtual bool SetOrder(ALuint order
)
1549 DUH_SIGRENDERER
*newrenderer
= pdumb_it_start_at_order(duh
, 2, order
);
1552 SetError("Could not set order");
1555 pduh_end_sigrenderer(renderer
);
1556 renderer
= newrenderer
;
1562 dumbStream(std::istream
*_fstream
)
1563 : alureStream(_fstream
), dumbFile(NULL
), duh(NULL
), renderer(NULL
),
1564 lastOrder(0), format(AL_NONE
), samplerate(48000)
1566 if(!dumb_handle
) return;
1568 ALCdevice
*device
= alcGetContextsDevice(alcGetCurrentContext());
1570 alcGetIntegerv(device
, ALC_FREQUENCY
, 1, &samplerate
);
1572 DUH
* (*funcs
[])(DUMBFILE
*) = {
1582 vfs
.getc
= read_char
;
1586 for(size_t i
= 0;funcs
[i
];i
++)
1588 dumbFile
= pdumbfile_open_ex(this, &vfs
);
1591 duh
= funcs
[i
](dumbFile
);
1594 renderer
= pdumb_it_start_at_order(duh
, 2, lastOrder
);
1597 pdumb_it_set_loop_callback(pduh_get_it_sigrenderer(renderer
), loop_cb
, this);
1605 pdumbfile_close(dumbFile
);
1613 virtual ~dumbStream()
1616 pduh_end_sigrenderer(renderer
);
1624 pdumbfile_close(dumbFile
);
1629 // DUMBFILE iostream callbacks
1630 static int skip(void *user_data
, long offset
)
1632 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1635 if(stream
->seekg(offset
, std::ios_base::cur
))
1640 static long read(char *ptr
, long size
, void *user_data
)
1642 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1645 stream
->read(ptr
, size
);
1646 return stream
->gcount();
1649 static int read_char(void *user_data
)
1651 std::istream
*stream
= static_cast<dumbStream
*>(user_data
)->fstream
;
1655 stream
->read(reinterpret_cast<char*>(&ret
), 1);
1656 if(stream
->gcount() > 0)
1661 static int loop_cb(void *user_data
)
1663 dumbStream
*self
= static_cast<dumbStream
*>(user_data
);
1664 pdumb_it_sr_set_speed(pduh_get_it_sigrenderer(self
->renderer
), 0);
1668 static DecoderDecl
<dumbStream
> dumbStream_decoder
;
1672 struct modStream
: public alureStream
{
1673 ModPlugFile
*modFile
;
1676 virtual bool IsValid()
1677 { return modFile
!= NULL
; }
1679 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1681 *fmt
= AL_FORMAT_STEREO16
;
1683 *blockalign
= 2 * sizeof(ALshort
);
1687 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1689 int ret
= pModPlug_Read(modFile
, data
, bytes
);
1690 if(ret
< 0) return 0;
1694 virtual bool Rewind()
1695 { return SetOrder(lastOrder
); }
1697 virtual bool SetOrder(ALuint order
)
1699 std::vector
<char> data(16384);
1701 while(total
< 2*1024*1024)
1703 fstream
->read(&data
[total
], data
.size()-total
);
1704 if(fstream
->gcount() == 0) break;
1705 total
+= fstream
->gcount();
1706 data
.resize(total
*2);
1710 ModPlugFile
*newMod
= pModPlug_Load(&data
[0], data
.size());
1713 SetError("Could not reload data");
1716 pModPlug_Unload(modFile
);
1719 // There seems to be no way to tell if the seek succeeds
1720 pModPlug_SeekOrder(modFile
, order
);
1726 modStream(std::istream
*_fstream
)
1727 : alureStream(_fstream
), modFile(NULL
), lastOrder(0)
1729 if(!mod_handle
) return;
1731 std::vector
<char> data(16384);
1733 while(total
< 2*1024*1024)
1735 fstream
->read(&data
[total
], data
.size()-total
);
1736 if(fstream
->gcount() == 0) break;
1737 total
+= fstream
->gcount();
1738 data
.resize(total
*2);
1742 modFile
= pModPlug_Load(&data
[0], data
.size());
1745 virtual ~modStream()
1748 pModPlug_Unload(modFile
);
1752 static DecoderDecl
<modStream
> modStream_decoder
;
1756 struct mp3Stream
: public alureStream
{
1757 mpg123_handle
*mp3File
;
1761 std::ios::pos_type dataStart
;
1762 std::ios::pos_type dataEnd
;
1764 virtual bool IsValid()
1765 { return mp3File
!= NULL
; }
1767 virtual bool GetFormat(ALenum
*fmt
, ALuint
*frequency
, ALuint
*blockalign
)
1770 *frequency
= samplerate
;
1771 *blockalign
= channels
*2;
1775 virtual ALuint
GetData(ALubyte
*data
, ALuint bytes
)
1781 int ret
= pmpg123_read(mp3File
, data
, bytes
, &got
);
1787 if(ret
== MPG123_NEW_FORMAT
)
1791 pmpg123_getformat(mp3File
, &newrate
, &newchans
, &enc
);
1794 if(ret
== MPG123_NEED_MORE
)
1796 unsigned char data
[4096];
1797 ALint insize
= std::min((ALint
)sizeof(data
),
1798 (ALint
)(dataEnd
-fstream
->tellg()));
1801 fstream
->read((char*)data
, insize
);
1802 insize
= fstream
->gcount();
1804 if(insize
> 0 && pmpg123_feed(mp3File
, data
, insize
) == MPG123_OK
)
1813 virtual bool Rewind()
1816 std::istream::pos_type oldpos
= fstream
->tellg();
1817 fstream
->seekg(dataStart
);
1819 mpg123_handle
*newFile
= pmpg123_new(NULL
, NULL
);
1820 if(pmpg123_open_feed(newFile
) == MPG123_OK
)
1822 unsigned char data
[4096];
1827 ALuint amt
, total
= 0;
1828 int ret
= MPG123_OK
;
1830 amt
= std::min((ALint
)sizeof(data
),
1831 (ALint
)(dataEnd
-fstream
->tellg()));
1832 fstream
->read((char*)data
, amt
);
1833 amt
= fstream
->gcount();
1836 ret
= pmpg123_decode(newFile
, data
, amt
, NULL
, 0, NULL
);
1837 } while(ret
== MPG123_NEED_MORE
&& total
< 64*1024);
1839 if(ret
== MPG123_NEW_FORMAT
&&
1840 pmpg123_getformat(newFile
, &newrate
, &newchans
, &enc
) == MPG123_OK
)
1842 if(pmpg123_format_none(newFile
) == MPG123_OK
&&
1843 pmpg123_format(newFile
, samplerate
, channels
, MPG123_ENC_SIGNED_16
) == MPG123_OK
)
1846 pmpg123_delete(mp3File
);
1851 pmpg123_delete(newFile
);
1854 fstream
->seekg(oldpos
);
1855 SetError("Restart failed");
1859 mp3Stream(std::istream
*_fstream
)
1860 : alureStream(_fstream
), mp3File(NULL
), format(AL_NONE
),
1861 dataStart(0), dataEnd(0)
1863 if(!mp123_handle
) return;
1865 if(!FindDataChunk())
1868 mp3File
= pmpg123_new(NULL
, NULL
);
1869 if(pmpg123_open_feed(mp3File
) == MPG123_OK
)
1871 unsigned char data
[4096];
1874 ALuint amt
, total
= 0;
1875 int ret
= MPG123_OK
;
1877 amt
= std::min((ALint
)sizeof(data
),
1878 (ALint
)(dataEnd
-fstream
->tellg()));
1879 fstream
->read((char*)data
, amt
);
1880 amt
= fstream
->gcount();
1883 ret
= pmpg123_decode(mp3File
, data
, amt
, NULL
, 0, NULL
);
1884 } while(ret
== MPG123_NEED_MORE
&& total
< 64*1024);
1886 if(ret
== MPG123_NEW_FORMAT
&&
1887 pmpg123_getformat(mp3File
, &samplerate
, &channels
, &enc
) == MPG123_OK
)
1889 format
= GetSampleFormat(channels
, 16, false);
1890 if(pmpg123_format_none(mp3File
) == MPG123_OK
&&
1891 pmpg123_format(mp3File
, samplerate
, channels
, MPG123_ENC_SIGNED_16
) == MPG123_OK
)
1898 pmpg123_delete(mp3File
);
1902 virtual ~mp3Stream()
1905 pmpg123_delete(mp3File
);
1910 bool FindDataChunk()
1915 if(!fstream
->read(reinterpret_cast<char*>(buffer
), 12))
1918 if(memcmp(buffer
, "RIFF", 4) != 0 || memcmp(buffer
+8, "WAVE", 4) != 0)
1922 // Check for an ID3v2 tag, and skip it
1923 if(memcmp(buffer
, "ID3", 3) == 0 &&
1924 buffer
[3] <= 4 && buffer
[4] != 0xff &&
1925 (buffer
[5]&0x0f) == 0 && (buffer
[6]&0x80) == 0 &&
1926 (buffer
[7]&0x80) == 0 && (buffer
[8]&0x80) == 0 &&
1927 (buffer
[9]&0x80) == 0)
1929 dataStart
= (buffer
[6]<<21) | (buffer
[7]<<14) |
1930 (buffer
[8]<< 7) | (buffer
[9] );
1931 dataStart
+= ((buffer
[5]&0x10) ? 20 : 10);
1934 if(fstream
->seekg(0, std::ios_base::end
))
1936 dataEnd
= fstream
->tellg();
1937 fstream
->seekg(dataStart
);
1946 if(!fstream
->read(tag
, 4))
1949 /* read chunk length */
1950 length
= read_le32(fstream
);
1952 if(memcmp(tag
, "fmt ", 4) == 0 && length
>= 16)
1954 /* Data type (should be 0x0050 or 0x0055 for MP3 data) */
1955 type
= read_le16(fstream
);
1956 if(type
!= 0x0050 && type
!= 0x0055)
1959 /* Ignore the rest of the chunk. Everything we need is in the
1962 else if(memcmp(tag
, "data", 4) == 0)
1964 if(type
== 0x0050 || type
== 0x0055)
1966 dataStart
= fstream
->tellg();
1967 dataEnd
= dataStart
;
1973 fstream
->seekg(length
, std::ios_base::cur
);
1979 static DecoderDecl
<mp3Stream
> mp3Stream_decoder
;
1983 template <typename T
>
1984 alureStream
*get_stream_decoder(const T
&fdata
)
1986 std::map
<ALint
,UserCallbacks
>::iterator i
= InstalledCallbacks
.begin();
1987 while(i
!= InstalledCallbacks
.end() && i
->first
< 0)
1989 std::auto_ptr
<alureStream
> stream(new customStream(fdata
, i
->second
));
1990 if(stream
->IsValid()) return stream
.release();
1994 std::istream
*file
= new InStream(fdata
);
1997 Decoder::ListType Factories
= Decoder::GetList();
1998 Decoder::ListType::iterator factory
= Factories
.begin();
1999 Decoder::ListType::iterator end
= Factories
.end();
2000 while(factory
!= end
)
2003 file
->seekg(0, std::ios_base::beg
);
2005 std::auto_ptr
<alureStream
> stream((*factory
)(file
));
2006 if(stream
.get() != NULL
) return stream
.release();
2011 SetError("Unsupported type");
2016 SetError("Failed to open file");
2020 while(i
!= InstalledCallbacks
.end())
2022 std::auto_ptr
<alureStream
> stream(new customStream(fdata
, i
->second
));
2023 if(stream
->IsValid()) return stream
.release();
2027 return new nullStream
;
2030 alureStream
*create_stream(const char *fname
)
2031 { return get_stream_decoder(fname
); }
2032 alureStream
*create_stream(const MemDataInfo
&memData
)
2033 { return get_stream_decoder(memData
); }
2035 alureStream
*create_stream(ALvoid
*userdata
, ALenum format
, ALuint rate
, const UserCallbacks
&cb
)
2036 { return new customStream(userdata
, format
, rate
, cb
); }