Add float and IMA4 support to the wave decoder
[alure.git] / src / streamdec.cpp
blobdb0fb285b3017957fdc3fc193ad4132afb6dcdcd
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 static inline ALuint read_le32(std::istream *file)
42 ALubyte buffer[4];
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)
49 ALubyte buffer[2];
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)
56 ALubyte buffer[4];
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)
63 ALubyte buffer[2];
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)
70 ALubyte buffer[10];
71 if(!file->read(reinterpret_cast<char*>(buffer), 10)) return 0;
72 ALuint mantissa, last = 0;
73 ALubyte exp = buffer[1];
74 exp = 30 - exp;
75 mantissa = (buffer[2]<<24) | (buffer[3]<<16) | (buffer[4]<<8) | buffer[5];
76 while (exp--)
78 last = mantissa;
79 mantissa >>= 1;
81 if((last&1)) mantissa++;
82 return 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 {
96 void *usrFile;
97 ALenum format;
98 ALuint samplerate;
99 ALuint blockAlign;
100 MemDataInfo memInfo;
102 UserCallbacks cb;
104 virtual bool IsValid()
105 { return usrFile != NULL; }
107 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
109 if(format == AL_NONE)
111 if(!cb.get_fmt ||
112 !cb.get_fmt(usrFile, &this->format, &samplerate, &blockAlign))
113 return false;
116 *fmt = format;
117 *frequency = samplerate;
118 *blockalign = blockAlign;
119 return true;
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))
128 return true;
129 SetError("Rewind failed");
130 return false;
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)
151 cb.close(usrFile);
152 usrFile = NULL;
157 struct wavStream : public alureStream {
158 ALenum format;
159 int samplerate;
160 int blockAlign;
161 int sampleSize;
162 long dataStart;
163 long dataLen;
164 size_t remLen;
166 virtual bool IsValid()
167 { return (dataStart > 0 && format != AL_NONE); }
169 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
171 *fmt = format;
172 *frequency = samplerate;
173 *blockalign = blockAlign;
174 return true;
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;
184 remLen -= got;
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]);
210 return got;
213 virtual bool Rewind()
215 fstream->clear();
216 if(fstream->seekg(dataStart))
218 remLen = dataLen;
219 return true;
222 SetError("Seek failed");
223 return false;
226 wavStream(std::istream *_fstream)
227 : alureStream(_fstream), format(0), dataStart(0)
229 ALubyte buffer[25];
230 int length;
232 if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
233 memcmp(buffer, "RIFF", 4) != 0 || memcmp(buffer+8, "WAVE", 4) != 0)
234 return;
236 while(!dataStart || format == AL_NONE)
238 char tag[4];
239 if(!fstream->read(tag, 4))
240 break;
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)
251 break;
253 /* mono or stereo data */
254 int channels = read_le16(fstream);
256 /* sample frequency */
257 samplerate = read_le32(fstream);
259 /* skip four bytes */
260 fstream->ignore(4);
262 /* bytes per block */
263 blockAlign = read_le16(fstream);
264 if(blockAlign == 0)
265 break;
267 /* bits per sample */
268 sampleSize = read_le16(fstream);
270 length -= 16;
272 /* Look for any extra data and try to find the format */
273 int extrabytes = 0;
274 if(length >= 2)
276 extrabytes = read_le16(fstream);
277 length -= 2;
279 extrabytes = std::min(extrabytes, length);
281 if(type == 0x0001)
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);
288 length -= 2;
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"))
295 if(channels == 1)
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);
315 virtual ~wavStream()
319 struct aiffStream : public alureStream {
320 ALenum format;
321 int samplerate;
322 int blockAlign;
323 int sampleSize;
324 long dataStart;
325 long dataLen;
326 size_t remLen;
328 virtual bool IsValid()
329 { return (dataStart > 0 && format != AL_NONE); }
331 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
333 *fmt = format;
334 *frequency = samplerate;
335 *blockalign = blockAlign;
336 return true;
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;
346 remLen -= got;
348 if(LittleEndian)
350 if(sampleSize == 2)
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]);
365 return got;
368 virtual bool Rewind()
370 fstream->clear();
371 if(fstream->seekg(dataStart))
373 remLen = dataLen;
374 return true;
377 SetError("Seek failed");
378 return false;
381 aiffStream(std::istream *_fstream)
382 : alureStream(_fstream), format(0), dataStart(0)
384 ALubyte buffer[25];
385 int length;
387 if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
388 memcmp(buffer, "FORM", 4) != 0 || memcmp(buffer+8, "AIFF", 4) != 0)
389 return;
391 while(!dataStart || format == AL_NONE)
393 char tag[4];
394 if(!fstream->read(tag, 4))
395 break;
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 */
406 fstream->ignore(4);
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);
419 length -= 18;
421 else if(memcmp(tag, "SSND", 4) == 0)
423 dataStart = fstream->tellg();
424 dataStart += 8;
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()
439 #ifdef HAS_SNDFILE
440 struct sndStream : public alureStream {
441 SNDFILE *sndFile;
442 SF_INFO sndInfo;
443 ALenum format;
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);
452 *fmt = format;
453 *frequency = sndInfo.samplerate;
454 *blockalign = sndInfo.channels*2;
455 return true;
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)
467 return true;
469 SetError("Seek failed");
470 return false;
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 = {
481 get_filelen, seek,
482 read, write, tell
484 sndFile = psf_open_virtual(&streamIO, SFM_READ, &sndInfo, this);
487 virtual ~sndStream()
489 if(sndFile)
490 psf_close(sndFile);
491 sndFile = NULL;
494 private:
495 // libSndFile iostream callbacks
496 static sf_count_t get_filelen(void *user_data)
498 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
499 stream->clear();
501 std::streampos len = -1;
502 std::streampos pos = stream->tellg();
503 if(stream->seekg(0, std::ios_base::end))
505 len = stream->tellg();
506 stream->seekg(pos);
509 return len;
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;
515 stream->clear();
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);
523 else
524 return -1;
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;
532 stream->clear();
533 stream->read(static_cast<char*>(ptr), count);
534 return stream->gcount();
537 static sf_count_t write(const void*, sf_count_t, void*)
538 { return -1; }
540 static sf_count_t tell(void *user_data)
542 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
543 stream->clear();
544 return stream->tellg();
547 #else
548 struct sndStream : public nullStream {
549 sndStream(std::istream*){}
551 #endif
553 #ifdef HAS_VORBISFILE
554 struct oggStream : public alureStream {
555 OggVorbis_File oggFile;
556 vorbis_info *oggInfo;
557 int oggBitstream;
558 ALenum format;
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);
567 *fmt = format;
568 *frequency = oggInfo->rate;
569 *blockalign = oggInfo->channels*2;
570 return true;
573 virtual ALuint GetData(ALubyte *data, ALuint bytes)
575 ALuint got = 0;
576 while(bytes > 0)
578 int res = pov_read(&oggFile, (char*)&data[got], bytes, BigEndian?1:0, 2, 1, &oggBitstream);
579 if(res <= 0)
580 break;
581 bytes -= res;
582 got += res;
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
586 // re-ordered
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]);
626 return got;
629 virtual bool Rewind()
631 if(pov_pcm_seek(&oggFile, 0) == 0)
632 return true;
634 SetError("Seek failed");
635 return false;
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);
650 if(!oggInfo)
651 pov_clear(&oggFile);
655 virtual ~oggStream()
657 if(oggInfo)
658 pov_clear(&oggFile);
659 oggInfo = NULL;
662 private:
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;
667 stream->clear();
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);
675 else
676 return -1;
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;
684 stream->clear();
686 stream->read(static_cast<char*>(ptr), nmemb*size);
687 size_t ret = stream->gcount();
688 return ret/size;
691 static long tell(void *user_data)
693 std::istream *stream = static_cast<oggStream*>(user_data)->fstream;
694 stream->clear();
695 return stream->tellg();
698 static int close(void*)
700 return 0;
703 #else
704 struct oggStream : public nullStream {
705 oggStream(std::istream*){}
707 #endif
709 #ifdef HAS_FLAC
710 struct flacStream : public alureStream {
711 FLAC__StreamDecoder *flacFile;
712 ALenum format;
713 ALuint samplerate;
714 ALuint blockAlign;
715 ALboolean useFloat;
717 std::vector<ALubyte> initialData;
719 ALubyte *outBytes;
720 ALuint outLen;
721 ALuint outTotal;
723 virtual bool IsValid()
724 { return flacFile != NULL; }
726 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
728 *fmt = format;
729 *frequency = samplerate;
730 *blockalign = blockAlign;
731 return true;
734 virtual ALuint GetData(ALubyte *data, ALuint bytes)
736 outBytes = data;
737 outTotal = 0;
738 outLen = bytes;
740 if(initialData.size() > 0)
742 size_t rem = std::min(initialData.size(), (size_t)bytes);
743 memcpy(data, &initialData[0], rem);
744 outTotal += 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)
752 break;
755 return outTotal;
758 virtual bool Rewind()
760 if(pFLAC__stream_decoder_seek_absolute(flacFile, 0) != false)
762 initialData.clear();
763 return true;
766 SetError("Seek failed");
767 return false;
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();
777 if(flacFile)
779 if(pFLAC__stream_decoder_init_stream(flacFile, ReadCallback, SeekCallback, TellCallback, LengthCallback, EofCallback, WriteCallback, MetadataCallback, ErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK)
781 if(InitFlac())
783 // all ok
784 return;
787 pFLAC__stream_decoder_finish(flacFile);
789 pFLAC__stream_decoder_delete(flacFile);
790 flacFile = NULL;
794 virtual ~flacStream()
796 if(flacFile)
798 pFLAC__stream_decoder_finish(flacFile);
799 pFLAC__stream_decoder_delete(flacFile);
800 flacFile = NULL;
804 private:
805 bool InitFlac()
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
810 // Ogg files.
811 outLen = 0;
812 outTotal = 0;
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)
817 break;
820 if(initialData.size() > 0)
821 return true;
822 return false;
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;
829 ALuint i = 0;
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;
840 bps = 32;
842 else bps = 16;
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)
861 if(useFloat)
862 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
863 buffer[c][i]/(float)0x7FFFFF :
864 buffer[c][i]/(float)0x800000);
865 else
866 ((ALshort*)data)[c] = buffer[c][i]>>8;
868 else if(frame->header.bits_per_sample == 32)
870 if(useFloat)
871 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
872 buffer[c][i]/(float)0x7FFFFFFF :
873 buffer[c][i]/(float)0x80000000u);
874 else
875 ((ALshort*)data)[c] = buffer[c][i]>>16;
878 self->outTotal += self->blockAlign;
879 data += self->blockAlign;
880 i++;
883 if(i < frame->header.blocksize)
885 ALuint blocklen = (frame->header.blocksize-i) *
886 self->blockAlign;
887 ALuint start = self->initialData.size();
889 self->initialData.resize(start+blocklen);
890 data = &self->initialData[start];
892 do {
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)
901 if(useFloat)
902 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
903 buffer[c][i]/(float)0x7FFFFF :
904 buffer[c][i]/(float)0x800000);
905 else
906 ((ALshort*)data)[c] = buffer[c][i]>>8;
908 else if(frame->header.bits_per_sample == 32)
910 if(useFloat)
911 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
912 buffer[c][i]/(float)0x7FFFFFFF :
913 buffer[c][i]/(float)0x80000000u);
914 else
915 ((ALshort*)data)[c] = buffer[c][i]>>16;
918 data += self->blockAlign;
919 i++;
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;
935 stream->clear();
937 if(*bytes <= 0)
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;
950 stream->clear();
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;
959 stream->clear();
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;
967 stream->clear();
969 std::streampos pos = stream->tellg();
970 if(stream->seekg(0, std::ios_base::end))
972 *stream_length = stream->tellg();
973 stream->seekg(pos);
976 if(!stream->good())
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;
986 #else
987 struct flacStream : public nullStream {
988 flacStream(std::istream*){}
990 #endif
993 #ifdef HAS_MPG123
994 struct mp3Stream : public alureStream {
995 mpg123_handle *mp3File;
996 long samplerate;
997 int channels;
998 ALenum format;
1000 virtual bool IsValid()
1001 { return mp3File != NULL; }
1003 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
1005 *fmt = format;
1006 *frequency = samplerate;
1007 *blockalign = channels*2;
1008 return true;
1011 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1013 ALuint amt = 0;
1014 while(bytes > 0)
1016 size_t got = 0;
1017 int ret = pmpg123_read(mp3File, data, bytes, &got);
1019 bytes -= got;
1020 data += got;
1021 amt += got;
1023 if(ret == MPG123_NEW_FORMAT)
1025 long newrate;
1026 int newchans, enc;
1027 pmpg123_getformat(mp3File, &newrate, &newchans, &enc);
1028 continue;
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)
1036 continue;
1038 if(got == 0)
1039 break;
1041 return amt;
1044 virtual bool Rewind()
1046 fstream->clear();
1047 std::istream::pos_type oldpos = fstream->tellg();
1048 fstream->seekg(0);
1050 mpg123_handle *newFile = pmpg123_new(NULL, NULL);
1051 if(pmpg123_open_feed(newFile) == MPG123_OK)
1053 unsigned char data[4096];
1054 long newrate;
1055 int newchans;
1056 int ret, enc;
1058 ALuint amt, total = 0;
1059 do {
1060 fstream->read((char*)data, sizeof(data));
1061 amt = fstream->gcount();
1062 if(amt == 0) break;
1063 total += amt;
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)
1073 // All OK
1074 pmpg123_delete(mp3File);
1075 mp3File = newFile;
1076 return true;
1079 pmpg123_delete(newFile);
1082 fstream->seekg(oldpos);
1083 SetError("Restart failed");
1084 return false;
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];
1096 int ret, enc;
1098 ALuint amt, total = 0;
1099 do {
1100 fstream->read((char*)data, sizeof(data));
1101 amt = fstream->gcount();
1102 if(amt == 0) break;
1103 total += amt;
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)
1114 // All OK
1115 return;
1119 pmpg123_delete(mp3File);
1120 mp3File = NULL;
1123 virtual ~mp3Stream()
1125 if(mp3File)
1126 pmpg123_delete(mp3File);
1127 mp3File = NULL;
1130 #else
1131 struct mp3Stream : public nullStream {
1132 mp3Stream(std::istream*){}
1134 #endif
1137 #ifdef HAS_DUMB
1138 struct dumbStream : public alureStream {
1139 DUMBFILE_SYSTEM vfs;
1140 DUMBFILE *dumbFile;
1141 DUH *duh;
1142 DUH_SIGRENDERER *renderer;
1143 std::vector<sample_t> sampleBuf;
1144 ALuint lastOrder;
1145 ALenum format;
1146 ALCint samplerate;
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;
1159 *fmt = format;
1160 *frequency = samplerate;
1161 *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
1162 sizeof(ALfloat));
1163 return true;
1166 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1168 ALuint ret = 0;
1170 if(pdumb_it_sr_get_speed(pduh_get_it_sigrenderer(renderer)) == 0)
1171 return 0;
1173 ALuint sample_count = bytes / ((format==AL_FORMAT_STEREO16) ?
1174 sizeof(ALshort) : sizeof(ALfloat));
1176 sampleBuf.resize(sample_count);
1177 sample_t *samples[] = {
1178 &sampleBuf[0]
1181 pdumb_silence(samples[0], sample_count);
1182 ret = pduh_sigrenderer_generate_samples(renderer, 1.0f, 65536.0f/samplerate, sample_count/2, samples);
1183 ret *= 2;
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);
1189 else
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));
1198 return ret;
1201 virtual bool Rewind()
1203 DUH_SIGRENDERER *newrenderer = pdumb_it_start_at_order(duh, 2, lastOrder);
1204 if(!newrenderer)
1206 SetError("Could start renderer");
1207 return false;
1209 pduh_end_sigrenderer(renderer);
1210 renderer = newrenderer;
1211 return true;
1214 virtual bool SetOrder(ALuint order)
1216 DUH_SIGRENDERER *newrenderer = pdumb_it_start_at_order(duh, 2, order);
1217 if(!newrenderer)
1219 SetError("Could not set order");
1220 return false;
1222 pduh_end_sigrenderer(renderer);
1223 renderer = newrenderer;
1225 lastOrder = order;
1226 return true;
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());
1236 if(device)
1237 alcGetIntegerv(device, ALC_FREQUENCY, 1, &samplerate);
1239 DUH* (*funcs[])(DUMBFILE*) = {
1240 pdumb_read_it,
1241 pdumb_read_xm,
1242 pdumb_read_s3m,
1243 pdumb_read_mod,
1244 NULL
1247 vfs.open = NULL;
1248 vfs.skip = skip;
1249 vfs.getc = read_char;
1250 vfs.getnc = read;
1251 vfs.close = NULL;
1253 for(size_t i = 0;funcs[i];i++)
1255 dumbFile = pdumbfile_open_ex(this, &vfs);
1256 if(dumbFile)
1258 duh = funcs[i](dumbFile);
1259 if(duh)
1261 renderer = pdumb_it_start_at_order(duh, 2, lastOrder);
1262 if(renderer)
1264 pdumb_it_set_loop_callback(pduh_get_it_sigrenderer(renderer), loop_cb, this);
1265 break;
1268 punload_duh(duh);
1269 duh = NULL;
1272 pdumbfile_close(dumbFile);
1273 dumbFile = NULL;
1275 fstream->clear();
1276 fstream->seekg(0);
1280 virtual ~dumbStream()
1282 if(renderer)
1283 pduh_end_sigrenderer(renderer);
1284 renderer = NULL;
1286 if(duh)
1287 punload_duh(duh);
1288 duh = NULL;
1290 if(dumbFile)
1291 pdumbfile_close(dumbFile);
1292 dumbFile = NULL;
1295 private:
1296 // DUMBFILE iostream callbacks
1297 static int skip(void *user_data, long offset)
1299 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1300 stream->clear();
1302 if(stream->seekg(offset, std::ios_base::cur))
1303 return 0;
1304 return -1;
1307 static long read(char *ptr, long size, void *user_data)
1309 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1310 stream->clear();
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;
1319 stream->clear();
1321 unsigned char ret;
1322 stream->read(reinterpret_cast<char*>(&ret), 1);
1323 if(stream->gcount() > 0)
1324 return ret;
1325 return -1;
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);
1332 return 0;
1335 #else
1336 struct dumbStream : public nullStream {
1337 dumbStream(std::istream*){}
1339 #endif
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())
1352 return stream;
1353 delete stream;
1354 i++;
1357 std::istream *file = new InStream(fdata);
1358 if(!file->fail())
1360 stream = new wavStream(file);
1361 if(stream->IsValid())
1362 return stream;
1363 delete stream;
1365 file->clear();
1366 file->seekg(0, std::ios_base::beg);
1367 stream = new aiffStream(file);
1368 if(stream->IsValid())
1369 return stream;
1370 delete stream;
1372 // Try libVorbisFile
1373 file->clear();
1374 file->seekg(0, std::ios_base::beg);
1375 stream = new oggStream(file);
1376 if(stream->IsValid())
1377 return stream;
1378 delete stream;
1380 // Try libFLAC
1381 file->clear();
1382 file->seekg(0, std::ios_base::beg);
1383 stream = new flacStream(file);
1384 if(stream->IsValid())
1385 return stream;
1386 delete stream;
1388 // Try DUMB
1389 file->clear();
1390 file->seekg(0, std::ios_base::beg);
1391 stream = new dumbStream(file);
1392 if(stream->IsValid())
1393 return stream;
1394 delete stream;
1396 // Try libSndFile
1397 file->clear();
1398 file->seekg(0, std::ios_base::beg);
1399 stream = new sndStream(file);
1400 if(stream->IsValid())
1401 return stream;
1402 delete stream;
1404 // Try MPG123
1405 file->clear();
1406 file->seekg(0, std::ios_base::beg);
1407 stream = new mp3Stream(file);
1408 if(stream->IsValid())
1409 return stream;
1410 delete stream;
1412 SetError("Unsupported type");
1413 delete file;
1415 else
1417 SetError("Failed to open file");
1418 delete file;
1421 while(i != InstalledCallbacks.end())
1423 stream = new customStream(fdata, i->second);
1424 if(stream->IsValid())
1425 return stream;
1426 delete stream;
1427 i++;
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); }