Invalidate the block alignment if it doesn't match the expected value
[alure.git] / src / streamdec.cpp
blob8b8c8fa1d479ea8050b85ebe7fac2374c4ce3c90
1 /*
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
21 * IN THE SOFTWARE.
24 #include "config.h"
26 #include "main.h"
28 #include <string.h>
30 #include <algorithm>
31 #include <vector>
32 #include <memory>
33 #include <string>
34 #include <istream>
35 #include <fstream>
36 #include <iostream>
37 #include <sstream>
40 struct Decoder {
41 typedef std::auto_ptr<alureStream>(*FactoryType)(std::istream*);
42 typedef std::vector<FactoryType> ListType;
44 static const ListType& GetList()
45 { return AddList(NULL); }
47 protected:
48 template<typename T>
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);
60 return FuncList;
63 template<typename T>
64 struct DecoderDecl : public Decoder {
65 DecoderDecl() { AddList(Factory<T>); }
69 static inline ALuint read_le32(std::istream *file)
71 ALubyte buffer[4];
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)
78 ALubyte buffer[2];
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)
85 ALubyte buffer[4];
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)
92 ALubyte buffer[2];
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)
99 ALubyte buffer[10];
100 if(!file->read(reinterpret_cast<char*>(buffer), 10)) return 0;
101 ALuint mantissa, last = 0;
102 ALubyte exp = buffer[1];
103 exp = 30 - exp;
104 mantissa = (buffer[2]<<24) | (buffer[3]<<16) | (buffer[4]<<8) | buffer[5];
105 while (exp--)
107 last = mantissa;
108 mantissa >>= 1;
110 if((last&1)) mantissa++;
111 return 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 {
125 void *usrFile;
126 ALenum format;
127 ALuint samplerate;
128 ALuint blockAlign;
129 MemDataInfo memInfo;
131 UserCallbacks cb;
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))
141 return false;
143 if(DetectBlockAlignment(format) != blockAlign)
144 blockAlign = 0;
146 *fmt = format;
147 *frequency = samplerate;
148 *blockalign = blockAlign;
149 return true;
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))
158 return true;
159 SetError("Rewind failed");
160 return false;
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)
181 cb.close(usrFile);
182 usrFile = NULL;
187 struct wavStream : public alureStream {
188 ALenum format;
189 int samplerate;
190 int blockAlign;
191 int sampleSize;
192 long dataStart;
193 long dataLen;
194 size_t remLen;
196 virtual bool IsValid()
197 { return (dataStart > 0 && format != AL_NONE); }
199 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
201 *fmt = format;
202 *frequency = samplerate;
203 *blockalign = blockAlign;
204 return true;
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;
214 remLen -= got;
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]);
240 return got;
243 virtual bool Rewind()
245 fstream->clear();
246 if(fstream->seekg(dataStart))
248 remLen = dataLen;
249 return true;
252 SetError("Seek failed");
253 return false;
256 wavStream(std::istream *_fstream)
257 : alureStream(_fstream), format(0), dataStart(0)
259 ALubyte buffer[25];
260 int length;
262 if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
263 memcmp(buffer, "RIFF", 4) != 0 || memcmp(buffer+8, "WAVE", 4) != 0)
264 return;
266 while(!dataStart || format == AL_NONE)
268 char tag[4];
269 if(!fstream->read(tag, 4))
270 break;
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)
281 break;
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 */
290 fstream->ignore(4);
292 /* bytes per block */
293 blockAlign = read_le16(fstream);
294 if(blockAlign == 0)
295 break;
297 /* bits per sample */
298 sampleSize = read_le16(fstream);
300 length -= 16;
302 /* Look for any extra data and try to find the format */
303 int extrabytes = 0;
304 if(length >= 2)
306 extrabytes = read_le16(fstream);
307 length -= 2;
309 extrabytes = std::min(extrabytes, length);
311 if(type == 0x0001)
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);
318 length -= 2;
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"))
325 if(channels == 1)
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);
345 virtual ~wavStream()
348 static DecoderDecl<wavStream> wavStream_decoder;
351 struct aiffStream : public alureStream {
352 ALenum format;
353 int samplerate;
354 int blockAlign;
355 int sampleSize;
356 long dataStart;
357 long dataLen;
358 size_t remLen;
360 virtual bool IsValid()
361 { return (dataStart > 0 && format != AL_NONE); }
363 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
365 *fmt = format;
366 *frequency = samplerate;
367 *blockalign = blockAlign;
368 return true;
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;
378 remLen -= got;
380 if(LittleEndian)
382 if(sampleSize == 2)
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]);
397 return got;
400 virtual bool Rewind()
402 fstream->clear();
403 if(fstream->seekg(dataStart))
405 remLen = dataLen;
406 return true;
409 SetError("Seek failed");
410 return false;
413 aiffStream(std::istream *_fstream)
414 : alureStream(_fstream), format(0), dataStart(0)
416 ALubyte buffer[25];
417 int length;
419 if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
420 memcmp(buffer, "FORM", 4) != 0 || memcmp(buffer+8, "AIFF", 4) != 0)
421 return;
423 while(!dataStart || format == AL_NONE)
425 char tag[4];
426 if(!fstream->read(tag, 4))
427 break;
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 */
438 fstream->ignore(4);
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);
451 length -= 18;
453 else if(memcmp(tag, "SSND", 4) == 0)
455 dataStart = fstream->tellg();
456 dataStart += 8;
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;
476 int oggBitstream;
477 ALenum format;
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);
486 *fmt = format;
487 *frequency = oggInfo->rate;
488 *blockalign = oggInfo->channels*2;
489 return true;
492 virtual ALuint GetData(ALubyte *data, ALuint bytes)
494 ALuint got = 0;
495 while(bytes > 0)
497 int res = pov_read(&oggFile, (char*)&data[got], bytes, BigEndian?1:0, 2, 1, &oggBitstream);
498 if(res <= 0)
499 break;
500 bytes -= res;
501 got += res;
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
505 // re-ordered
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]);
545 return got;
548 virtual bool Rewind()
550 if(pov_pcm_seek(&oggFile, 0) == 0)
551 return true;
553 SetError("Seek failed");
554 return false;
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);
569 if(!oggInfo)
570 pov_clear(&oggFile);
574 virtual ~oggStream()
576 if(oggInfo)
577 pov_clear(&oggFile);
578 oggInfo = NULL;
581 private:
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;
586 stream->clear();
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);
594 else
595 return -1;
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;
603 stream->clear();
605 stream->read(static_cast<char*>(ptr), nmemb*size);
606 size_t ret = stream->gcount();
607 return ret/size;
610 static long tell(void *user_data)
612 std::istream *stream = static_cast<oggStream*>(user_data)->fstream;
613 stream->clear();
614 return stream->tellg();
617 static int close(void*)
619 return 0;
622 static DecoderDecl<oggStream> oggStream_decoder;
623 #endif
625 #ifdef HAS_FLAC
626 struct flacStream : public alureStream {
627 FLAC__StreamDecoder *flacFile;
628 ALenum format;
629 ALuint samplerate;
630 ALuint blockAlign;
631 ALboolean useFloat;
633 std::vector<ALubyte> initialData;
635 ALubyte *outBytes;
636 ALuint outLen;
637 ALuint outTotal;
639 virtual bool IsValid()
640 { return flacFile != NULL; }
642 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
644 *fmt = format;
645 *frequency = samplerate;
646 *blockalign = blockAlign;
647 return true;
650 virtual ALuint GetData(ALubyte *data, ALuint bytes)
652 outBytes = data;
653 outTotal = 0;
654 outLen = bytes;
656 if(initialData.size() > 0)
658 size_t rem = std::min(initialData.size(), (size_t)bytes);
659 memcpy(data, &initialData[0], rem);
660 outTotal += 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)
668 break;
671 return outTotal;
674 virtual bool Rewind()
676 if(pFLAC__stream_decoder_seek_absolute(flacFile, 0) != false)
678 initialData.clear();
679 return true;
682 SetError("Seek failed");
683 return false;
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();
693 if(flacFile)
695 if(pFLAC__stream_decoder_init_stream(flacFile, ReadCallback, SeekCallback, TellCallback, LengthCallback, EofCallback, WriteCallback, MetadataCallback, ErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK)
697 if(InitFlac())
699 // all ok
700 return;
703 pFLAC__stream_decoder_finish(flacFile);
705 pFLAC__stream_decoder_delete(flacFile);
706 flacFile = NULL;
710 virtual ~flacStream()
712 if(flacFile)
714 pFLAC__stream_decoder_finish(flacFile);
715 pFLAC__stream_decoder_delete(flacFile);
716 flacFile = NULL;
720 private:
721 bool InitFlac()
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
726 // Ogg files.
727 outLen = 0;
728 outTotal = 0;
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)
733 break;
736 if(initialData.size() > 0)
737 return true;
738 return false;
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;
745 ALuint i = 0;
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;
756 bps = 32;
758 else bps = 16;
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)
777 if(useFloat)
778 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
779 buffer[c][i]/(float)0x7FFFFF :
780 buffer[c][i]/(float)0x800000);
781 else
782 ((ALshort*)data)[c] = buffer[c][i]>>8;
784 else if(frame->header.bits_per_sample == 32)
786 if(useFloat)
787 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
788 buffer[c][i]/(float)0x7FFFFFFF :
789 buffer[c][i]/(float)0x80000000u);
790 else
791 ((ALshort*)data)[c] = buffer[c][i]>>16;
794 self->outTotal += self->blockAlign;
795 data += self->blockAlign;
796 i++;
799 if(i < frame->header.blocksize)
801 ALuint blocklen = (frame->header.blocksize-i) *
802 self->blockAlign;
803 ALuint start = self->initialData.size();
805 self->initialData.resize(start+blocklen);
806 data = &self->initialData[start];
808 do {
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)
817 if(useFloat)
818 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
819 buffer[c][i]/(float)0x7FFFFF :
820 buffer[c][i]/(float)0x800000);
821 else
822 ((ALshort*)data)[c] = buffer[c][i]>>8;
824 else if(frame->header.bits_per_sample == 32)
826 if(useFloat)
827 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
828 buffer[c][i]/(float)0x7FFFFFFF :
829 buffer[c][i]/(float)0x80000000u);
830 else
831 ((ALshort*)data)[c] = buffer[c][i]>>16;
834 data += self->blockAlign;
835 i++;
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;
851 stream->clear();
853 if(*bytes <= 0)
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;
866 stream->clear();
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;
875 stream->clear();
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;
883 stream->clear();
885 std::streampos pos = stream->tellg();
886 if(stream->seekg(0, std::ios_base::end))
888 *stream_length = stream->tellg();
889 stream->seekg(pos);
892 if(!stream->good())
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;
903 #endif
905 #ifdef HAS_FLUIDSYNTH
906 struct fluidStream : public alureStream {
907 private:
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
929 struct MidiTrack {
930 std::vector<ALubyte> data;
931 size_t Offset;
932 ALubyte LastEvent;
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)
942 void Reset()
944 Offset = 0;
945 LastEvent = 0;
946 SamplesLeft = 0.;
949 const MidiTrack& operator=(const MidiTrack &rhs)
951 data = rhs.data;
952 Offset = rhs.Offset;
953 LastEvent = rhs.LastEvent;
954 SamplesLeft = rhs.SamplesLeft;
955 return *this;
958 unsigned long ReadVarLen()
960 if(Offset >= data.size())
961 return 0;
963 unsigned long len = data[Offset]&0x7F;
964 while((data[Offset]&0x80))
966 if(++Offset >= data.size())
967 return 0;
968 len = (len<<7) | (data[Offset]&0x7F);
970 Offset++;
972 return len;
976 ALuint Divisions;
977 std::vector<MidiTrack> Tracks;
979 ALenum format;
980 ALsizei sampleRate;
981 ALdouble samplesPerTick;
983 fluid_settings_t *fluidSettings;
984 fluid_synth_t *fluidSynth;
985 int fontID;
987 public:
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;
999 *fmt = format;
1000 *frequency = sampleRate;
1001 *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
1002 sizeof(ALfloat));
1003 return true;
1006 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1008 ALuint ret;
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);
1016 else
1018 ALfloat *ptr = reinterpret_cast<ALfloat*>(data);
1019 ret = FillBuffer(ptr, bytes/2/sizeof(ALfloat));
1020 ret *= 2 * sizeof(ALfloat);
1023 return ret;
1026 virtual bool Rewind()
1028 for(std::vector<MidiTrack>::iterator i = Tracks.begin(), end = Tracks.end();i != end;i++)
1030 i->Reset();
1031 unsigned long val = i->ReadVarLen();
1032 i->SamplesLeft += val * samplesPerTick;
1034 pfluid_synth_program_reset(fluidSynth);
1035 UpdateTempo(500000);
1036 return true;
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");
1045 return false;
1048 if(fontID != FLUID_FAILED)
1049 pfluid_synth_sfunload(fluidSynth, fontID, true);
1050 fontID = newid;
1052 return 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());
1063 if(device)
1064 alcGetIntegerv(device, ALC_FREQUENCY, 1, &sampleRate);
1066 char hdr[4];
1067 if(!fstream->read(hdr, 4))
1068 return;
1070 if(memcmp(hdr, "MThd", 4) == 0)
1072 ALuint len = read_be32(fstream);
1073 if(len != 6)
1074 return;
1076 int type = read_be16(fstream);
1077 if(type != 0 && type != 1)
1078 return;
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)
1089 return;
1091 ALuint len = read_be32(fstream);
1092 i->data.resize(len);
1093 if(!fstream->read(reinterpret_cast<char*>(&i->data[0]), len))
1094 return;
1096 unsigned long val = i->ReadVarLen();
1097 i->SamplesLeft += val * samplesPerTick;
1099 SetupSynth();
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);
1111 fluidSynth = NULL;
1113 if(fluidSettings != NULL)
1114 pdelete_fluid_settings(fluidSettings);
1115 fluidSettings = NULL;
1118 private:
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);
1134 TracksPlaying++;
1137 if(TracksPlaying == 0)
1138 break;
1140 if(SamplesToDo == 0)
1142 ProcessMidi();
1143 continue;
1146 // Render samples
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); }
1167 void ProcessMidi()
1169 ALuint newtempo = 0;
1171 // Process more events
1172 std::vector<MidiTrack>::iterator i=Tracks.begin(), end=Tracks.end();
1173 while(i != end)
1175 if(i->Offset >= i->data.size() || i->SamplesLeft >= 1.)
1177 i++;
1178 continue;
1181 if(i->data.size() - i->Offset < 3)
1183 i->Offset = i->data.size();
1184 i++;
1185 continue;
1188 ALubyte event = i->data[i->Offset++];
1189 ALubyte parm1, parm2;
1190 if(!(event&0x80))
1192 event = i->LastEvent;
1193 i->Offset--;
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)
1203 case MIDI_NOTEOFF:
1204 pfluid_synth_noteoff(fluidSynth, channel, parm1);
1205 i->Offset += 2;
1206 break;
1207 case MIDI_NOTEON:
1208 pfluid_synth_noteon(fluidSynth, channel, parm1, parm2);
1209 i->Offset += 2;
1210 break;
1211 case MIDI_POLYPRESS:
1212 i->Offset += 2;
1213 break;
1215 case MIDI_CTRLCHANGE:
1216 pfluid_synth_cc(fluidSynth, channel, parm1, parm2);
1217 i->Offset += 2;
1218 break;
1219 case MIDI_PRGMCHANGE:
1220 pfluid_synth_program_change(fluidSynth, channel, parm1);
1221 i->Offset += 1;
1222 break;
1224 case MIDI_CHANPRESS:
1225 pfluid_synth_channel_pressure(fluidSynth, channel, parm1);
1226 i->Offset += 1;
1227 break;
1229 case MIDI_PITCHBEND:
1230 pfluid_synth_pitch_bend(fluidSynth, channel, (parm1&0x7F) | ((parm2&0x7F)<<7));
1231 i->Offset += 2;
1232 break;
1234 case MIDI_SPECIAL:
1235 switch(event)
1237 case MIDI_SYSEX:
1239 unsigned long len = i->ReadVarLen();
1240 if(i->data.size() - i->Offset < len)
1242 i->Offset = i->data.size();
1243 break;
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);
1251 i->Offset += len;
1252 break;
1254 case MIDI_SYSEXEND:
1256 unsigned long len = i->ReadVarLen();
1257 if(i->data.size() - i->Offset < len)
1259 i->Offset = i->data.size();
1260 break;
1262 i->Offset += len;
1263 break;
1266 case MIDI_SONGPOS:
1267 i->Offset += 2;
1268 break;
1270 case MIDI_SONGSEL:
1271 i->Offset += 1;
1272 break;
1274 case MIDI_META:
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();
1282 break;
1285 if(metatype == MIDI_META_EOT)
1287 i->Offset = i->data.size();
1288 break;
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]);
1298 i->Offset += val;
1299 break;
1302 default:
1303 /* The rest of the special events don't have any
1304 * data bytes */
1305 break;
1307 break;
1309 default:
1310 /* Shouldn't ever get to here */
1311 break;
1314 unsigned long val = i->ReadVarLen();
1315 i->SamplesLeft += val * samplesPerTick;
1317 if(newtempo)
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())
1329 continue;
1330 i->SamplesLeft = i->SamplesLeft / samplesPerTick * sampletickrate;
1332 samplesPerTick = sampletickrate;
1335 void SetupSynth()
1337 fluidSettings = pnew_fluid_settings();
1338 if(fluidSettings)
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);
1347 if(fluidSynth)
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;
1357 #endif
1359 #ifdef HAS_SNDFILE
1360 struct sndStream : public alureStream {
1361 SNDFILE *sndFile;
1362 SF_INFO sndInfo;
1363 ALenum format;
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);
1372 *fmt = format;
1373 *frequency = sndInfo.samplerate;
1374 *blockalign = sndInfo.channels*2;
1375 return true;
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)
1387 return true;
1389 SetError("Seek failed");
1390 return false;
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 = {
1401 get_filelen, seek,
1402 read, write, tell
1404 sndFile = psf_open_virtual(&streamIO, SFM_READ, &sndInfo, this);
1407 virtual ~sndStream()
1409 if(sndFile)
1410 psf_close(sndFile);
1411 sndFile = NULL;
1414 private:
1415 // libSndFile iostream callbacks
1416 static sf_count_t get_filelen(void *user_data)
1418 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
1419 stream->clear();
1421 std::streampos len = -1;
1422 std::streampos pos = stream->tellg();
1423 if(stream->seekg(0, std::ios_base::end))
1425 len = stream->tellg();
1426 stream->seekg(pos);
1429 return len;
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;
1435 stream->clear();
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);
1443 else
1444 return -1;
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;
1452 stream->clear();
1453 stream->read(static_cast<char*>(ptr), count);
1454 return stream->gcount();
1457 static sf_count_t write(const void*, sf_count_t, void*)
1458 { return -1; }
1460 static sf_count_t tell(void *user_data)
1462 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
1463 stream->clear();
1464 return stream->tellg();
1467 static DecoderDecl<sndStream> sndStream_decoder;
1468 #endif
1470 #ifdef HAS_DUMB
1471 struct dumbStream : public alureStream {
1472 DUMBFILE_SYSTEM vfs;
1473 DUMBFILE *dumbFile;
1474 DUH *duh;
1475 DUH_SIGRENDERER *renderer;
1476 std::vector<sample_t> sampleBuf;
1477 ALuint lastOrder;
1478 ALenum format;
1479 ALCint samplerate;
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;
1492 *fmt = format;
1493 *frequency = samplerate;
1494 *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
1495 sizeof(ALfloat));
1496 return true;
1499 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1501 ALuint ret = 0;
1503 if(pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(renderer)) == 0)
1504 return 0;
1506 ALuint sample_count = bytes / ((format==AL_FORMAT_STEREO16) ?
1507 sizeof(ALshort) : sizeof(ALfloat));
1509 sampleBuf.resize(sample_count);
1510 sample_t *samples[] = {
1511 &sampleBuf[0]
1514 pdumb_silence(samples[0], sample_count);
1515 ret = pduh_sigrenderer_generate_samples(renderer, 1.0f, 65536.0f/samplerate, sample_count/2, samples);
1516 ret *= 2;
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);
1522 else
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));
1531 return ret;
1534 virtual bool Rewind()
1536 DUH_SIGRENDERER *newrenderer = pdumb_it_start_at_order(duh, 2, lastOrder);
1537 if(!newrenderer)
1539 SetError("Could not start renderer");
1540 return false;
1542 pduh_end_sigrenderer(renderer);
1543 renderer = newrenderer;
1544 return true;
1547 virtual bool SetOrder(ALuint order)
1549 DUH_SIGRENDERER *newrenderer = pdumb_it_start_at_order(duh, 2, order);
1550 if(!newrenderer)
1552 SetError("Could not set order");
1553 return false;
1555 pduh_end_sigrenderer(renderer);
1556 renderer = newrenderer;
1558 lastOrder = order;
1559 return true;
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());
1569 if(device)
1570 alcGetIntegerv(device, ALC_FREQUENCY, 1, &samplerate);
1572 DUH* (*funcs[])(DUMBFILE*) = {
1573 pdumb_read_it,
1574 pdumb_read_xm,
1575 pdumb_read_s3m,
1576 pdumb_read_mod,
1577 NULL
1580 vfs.open = NULL;
1581 vfs.skip = skip;
1582 vfs.getc = read_char;
1583 vfs.getnc = read;
1584 vfs.close = NULL;
1586 for(size_t i = 0;funcs[i];i++)
1588 dumbFile = pdumbfile_open_ex(this, &vfs);
1589 if(dumbFile)
1591 duh = funcs[i](dumbFile);
1592 if(duh)
1594 renderer = pdumb_it_start_at_order(duh, 2, lastOrder);
1595 if(renderer)
1597 pdumb_it_set_loop_callback(pduh_get_it_sigrenderer(renderer), loop_cb, this);
1598 break;
1601 punload_duh(duh);
1602 duh = NULL;
1605 pdumbfile_close(dumbFile);
1606 dumbFile = NULL;
1608 fstream->clear();
1609 fstream->seekg(0);
1613 virtual ~dumbStream()
1615 if(renderer)
1616 pduh_end_sigrenderer(renderer);
1617 renderer = NULL;
1619 if(duh)
1620 punload_duh(duh);
1621 duh = NULL;
1623 if(dumbFile)
1624 pdumbfile_close(dumbFile);
1625 dumbFile = NULL;
1628 private:
1629 // DUMBFILE iostream callbacks
1630 static int skip(void *user_data, long offset)
1632 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1633 stream->clear();
1635 if(stream->seekg(offset, std::ios_base::cur))
1636 return 0;
1637 return -1;
1640 static long read(char *ptr, long size, void *user_data)
1642 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1643 stream->clear();
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;
1652 stream->clear();
1654 unsigned char ret;
1655 stream->read(reinterpret_cast<char*>(&ret), 1);
1656 if(stream->gcount() > 0)
1657 return ret;
1658 return -1;
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);
1665 return 0;
1668 static DecoderDecl<dumbStream> dumbStream_decoder;
1669 #endif
1671 #ifdef HAS_MODPLUG
1672 struct modStream : public alureStream {
1673 ModPlugFile *modFile;
1674 int lastOrder;
1676 virtual bool IsValid()
1677 { return modFile != NULL; }
1679 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
1681 *fmt = AL_FORMAT_STEREO16;
1682 *frequency = 44100;
1683 *blockalign = 2 * sizeof(ALshort);
1684 return true;
1687 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1689 int ret = pModPlug_Read(modFile, data, bytes);
1690 if(ret < 0) return 0;
1691 return ret;
1694 virtual bool Rewind()
1695 { return SetOrder(lastOrder); }
1697 virtual bool SetOrder(ALuint order)
1699 std::vector<char> data(16384);
1700 ALuint total = 0;
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);
1708 data.resize(total);
1710 ModPlugFile *newMod = pModPlug_Load(&data[0], data.size());
1711 if(!newMod)
1713 SetError("Could not reload data");
1714 return false;
1716 pModPlug_Unload(modFile);
1717 modFile = newMod;
1719 // There seems to be no way to tell if the seek succeeds
1720 pModPlug_SeekOrder(modFile, order);
1721 lastOrder = order;
1723 return true;
1726 modStream(std::istream *_fstream)
1727 : alureStream(_fstream), modFile(NULL), lastOrder(0)
1729 if(!mod_handle) return;
1731 std::vector<char> data(16384);
1732 ALuint total = 0;
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);
1740 data.resize(total);
1742 modFile = pModPlug_Load(&data[0], data.size());
1745 virtual ~modStream()
1747 if(modFile)
1748 pModPlug_Unload(modFile);
1749 modFile = NULL;
1752 static DecoderDecl<modStream> modStream_decoder;
1753 #endif
1755 #ifdef HAS_MPG123
1756 struct mp3Stream : public alureStream {
1757 mpg123_handle *mp3File;
1758 long samplerate;
1759 int channels;
1760 ALenum format;
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)
1769 *fmt = format;
1770 *frequency = samplerate;
1771 *blockalign = channels*2;
1772 return true;
1775 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1777 ALuint amt = 0;
1778 while(bytes > 0)
1780 size_t got = 0;
1781 int ret = pmpg123_read(mp3File, data, bytes, &got);
1783 bytes -= got;
1784 data += got;
1785 amt += got;
1787 if(ret == MPG123_NEW_FORMAT)
1789 long newrate;
1790 int newchans, enc;
1791 pmpg123_getformat(mp3File, &newrate, &newchans, &enc);
1792 continue;
1794 if(ret == MPG123_NEED_MORE)
1796 unsigned char data[4096];
1797 ALint insize = std::min((ALint)sizeof(data),
1798 (ALint)(dataEnd-fstream->tellg()));
1799 if(insize > 0)
1801 fstream->read((char*)data, insize);
1802 insize = fstream->gcount();
1804 if(insize > 0 && pmpg123_feed(mp3File, data, insize) == MPG123_OK)
1805 continue;
1807 if(got == 0)
1808 break;
1810 return amt;
1813 virtual bool Rewind()
1815 fstream->clear();
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];
1823 long newrate;
1824 int newchans;
1825 int enc;
1827 ALuint amt, total = 0;
1828 int ret = MPG123_OK;
1829 do {
1830 amt = std::min((ALint)sizeof(data),
1831 (ALint)(dataEnd-fstream->tellg()));
1832 fstream->read((char*)data, amt);
1833 amt = fstream->gcount();
1834 if(amt == 0) break;
1835 total += amt;
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)
1845 // All OK
1846 pmpg123_delete(mp3File);
1847 mp3File = newFile;
1848 return true;
1851 pmpg123_delete(newFile);
1854 fstream->seekg(oldpos);
1855 SetError("Restart failed");
1856 return false;
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())
1866 return;
1868 mp3File = pmpg123_new(NULL, NULL);
1869 if(pmpg123_open_feed(mp3File) == MPG123_OK)
1871 unsigned char data[4096];
1872 int enc;
1874 ALuint amt, total = 0;
1875 int ret = MPG123_OK;
1876 do {
1877 amt = std::min((ALint)sizeof(data),
1878 (ALint)(dataEnd-fstream->tellg()));
1879 fstream->read((char*)data, amt);
1880 amt = fstream->gcount();
1881 if(amt == 0) break;
1882 total += amt;
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)
1893 // All OK
1894 return;
1898 pmpg123_delete(mp3File);
1899 mp3File = NULL;
1902 virtual ~mp3Stream()
1904 if(mp3File)
1905 pmpg123_delete(mp3File);
1906 mp3File = NULL;
1909 private:
1910 bool FindDataChunk()
1912 ALubyte buffer[25];
1913 int length;
1915 if(!fstream->read(reinterpret_cast<char*>(buffer), 12))
1916 return false;
1918 if(memcmp(buffer, "RIFF", 4) != 0 || memcmp(buffer+8, "WAVE", 4) != 0)
1920 dataStart = 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);
1939 return true;
1942 int type = 0;
1943 while(1)
1945 char tag[4];
1946 if(!fstream->read(tag, 4))
1947 break;
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)
1957 break;
1958 length -= 2;
1959 /* Ignore the rest of the chunk. Everything we need is in the
1960 * data stream */
1962 else if(memcmp(tag, "data", 4) == 0)
1964 if(type == 0x0050 || type == 0x0055)
1966 dataStart = fstream->tellg();
1967 dataEnd = dataStart;
1968 dataEnd += length;
1969 return true;
1973 fstream->seekg(length, std::ios_base::cur);
1976 return false;
1979 static DecoderDecl<mp3Stream> mp3Stream_decoder;
1980 #endif
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();
1991 i++;
1994 std::istream *file = new InStream(fdata);
1995 if(!file->fail())
1997 Decoder::ListType Factories = Decoder::GetList();
1998 Decoder::ListType::iterator factory = Factories.begin();
1999 Decoder::ListType::iterator end = Factories.end();
2000 while(factory != end)
2002 file->clear();
2003 file->seekg(0, std::ios_base::beg);
2005 std::auto_ptr<alureStream> stream((*factory)(file));
2006 if(stream.get() != NULL) return stream.release();
2008 factory++;
2011 SetError("Unsupported type");
2012 delete file;
2014 else
2016 SetError("Failed to open file");
2017 delete file;
2020 while(i != InstalledCallbacks.end())
2022 std::auto_ptr<alureStream> stream(new customStream(fdata, i->second));
2023 if(stream->IsValid()) return stream.release();
2024 i++;
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); }