More IO callback fixes
[alure.git] / src / streamdec.cpp
blobf3e0fa9389ccdf854fc5f65c11450f8121c3df58
1 /*
2 * ALURE OpenAL utility library
3 * Copyright (C) 2009-2010 by Chris Robinson.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include "main.h"
25 #include <string.h>
27 #include <algorithm>
28 #include <vector>
29 #include <memory>
30 #include <string>
31 #include <istream>
32 #include <fstream>
33 #include <iostream>
34 #include <sstream>
37 static inline ALuint read_le32(std::istream *file)
39 ALubyte buffer[4];
40 if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
41 return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24);
44 static inline ALushort read_le16(std::istream *file)
46 ALubyte buffer[2];
47 if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
48 return buffer[0] | (buffer[1]<<8);
51 static inline ALuint read_be32(std::istream *file)
53 ALubyte buffer[4];
54 if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
55 return (buffer[0]<<24) | (buffer[1]<<16) | (buffer[2]<<8) | buffer[3];
58 static inline ALushort read_be16(std::istream *file)
60 ALubyte buffer[2];
61 if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
62 return (buffer[0]<<8) | buffer[1];
65 static inline ALuint read_be80extended(std::istream *file)
67 ALubyte buffer[10];
68 if(!file->read(reinterpret_cast<char*>(buffer), 10)) return 0;
69 ALuint mantissa, last = 0;
70 ALubyte exp = buffer[1];
71 exp = 30 - exp;
72 mantissa = (buffer[2]<<24) | (buffer[3]<<16) | (buffer[4]<<8) | buffer[5];
73 while (exp--)
75 last = mantissa;
76 mantissa >>= 1;
78 if((last&1)) mantissa++;
79 return mantissa;
83 bool customStream::IsValid()
84 { return usrFile != NULL; }
86 bool customStream::GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
88 if(format == 0)
90 if(!cb.get_fmt ||
91 !cb.get_fmt(usrFile, &this->format, &samplerate, &blockAlign))
92 return false;
95 *fmt = format;
96 *frequency = samplerate;
97 *blockalign = blockAlign;
98 return true;
101 ALuint customStream::GetData(ALubyte *data, ALuint bytes)
102 { return cb.decode(usrFile, data, bytes); }
104 bool customStream::Rewind()
106 if(cb.rewind && cb.rewind(usrFile))
107 return true;
108 SetError("Rewind failed");
109 return false;
112 customStream::customStream(const char *fname, const UserCallbacks &callbacks)
113 : alureStream(NULL), usrFile(NULL), format(0), samplerate(0), blockAlign(0),
114 cb(callbacks)
115 { if(cb.open_file) usrFile = cb.open_file(fname); }
117 customStream::customStream(const MemDataInfo &memData, const UserCallbacks &callbacks)
118 : alureStream(NULL), usrFile(NULL), format(0), samplerate(0), blockAlign(0),
119 memInfo(memData), cb(callbacks)
120 { if(cb.open_mem) usrFile = cb.open_mem(memInfo.Data, memInfo.Length); }
122 customStream::customStream(void *userdata, ALenum fmt, ALuint srate, const UserCallbacks &callbacks)
123 : alureStream(NULL), usrFile(userdata), format(fmt), samplerate(srate),
124 blockAlign(DetectBlockAlignment(format)), cb(callbacks)
127 customStream::~customStream()
129 if(cb.close && usrFile)
130 cb.close(usrFile);
131 usrFile = NULL;
135 struct nullStream : public alureStream {
136 virtual bool IsValid() { return false; }
137 virtual bool GetFormat(ALenum*,ALuint*,ALuint*) { return false; }
138 virtual ALuint GetData(ALubyte*,ALuint) { return 0; }
139 virtual bool Rewind() { return false; }
140 nullStream():alureStream(NULL) {}
144 struct wavStream : public alureStream {
145 ALenum format;
146 int samplerate;
147 int blockAlign;
148 int sampleSize;
149 long dataStart;
150 long dataLen;
151 size_t remLen;
153 virtual bool IsValid()
154 { return (dataStart > 0 && format != AL_NONE); }
156 virtual bool GetFormat(ALenum *format, ALuint *frequency, ALuint *blockalign)
158 *format = this->format;
159 *frequency = samplerate;
160 *blockalign = blockAlign;
161 return true;
164 virtual ALuint GetData(ALubyte *data, ALuint bytes)
166 std::streamsize rem = ((remLen >= bytes) ? bytes : remLen) / blockAlign;
167 fstream->read(reinterpret_cast<char*>(data), rem*blockAlign);
169 std::streamsize got = fstream->gcount();
170 got -= got%blockAlign;
171 remLen -= got;
173 if(BigEndian && sampleSize > 1)
175 if(sampleSize == 2)
176 for(std::streamsize i = 0;i < got;i+=2)
178 ALubyte tmp = data[i];
179 data[i] = data[i+1];
180 data[i+1] = tmp;
182 else if(sampleSize == 4)
183 for(std::streamsize i = 0;i < got;i+=4)
185 ALubyte tmp = data[i];
186 data[i] = data[i+3];
187 data[i+3] = tmp;
188 tmp = data[i+1];
189 data[i+1] = data[i+2];
190 data[i+2] = tmp;
194 return got;
197 virtual bool Rewind()
199 fstream->clear();
200 if(fstream->seekg(dataStart))
202 remLen = dataLen;
203 return true;
206 SetError("Seek failed");
207 return false;
210 wavStream(std::istream *_fstream)
211 : alureStream(_fstream), format(0), dataStart(0)
212 { Init(); }
214 virtual ~wavStream()
217 private:
218 void Init()
220 ALubyte buffer[25];
221 int length;
223 if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
224 memcmp(buffer, "RIFF", 4) != 0 || memcmp(buffer+8, "WAVE", 4) != 0)
225 return;
227 while(!dataStart || format == AL_NONE)
229 char tag[4];
230 if(!fstream->read(tag, 4))
231 break;
233 /* read chunk length */
234 length = read_le32(fstream);
236 if(memcmp(tag, "fmt ", 4) == 0 && length >= 16)
238 /* Data type (should be 1 for PCM data) */
239 int type = read_le16(fstream);
240 if(type != 1)
241 break;
243 /* mono or stereo data */
244 int channels = read_le16(fstream);
246 /* sample frequency */
247 samplerate = read_le32(fstream);
249 /* skip four bytes */
250 fstream->ignore(4);
252 /* bytes per block */
253 blockAlign = read_le16(fstream);
254 if(blockAlign == 0)
255 break;
257 /* bits per sample */
258 sampleSize = read_le16(fstream) / 8;
260 format = alureGetSampleFormat(channels, sampleSize*8, 0);
262 length -= 16;
264 else if(memcmp(tag, "data", 4) == 0)
266 dataStart = fstream->tellg();
267 dataLen = remLen = length;
270 fstream->seekg(length, std::ios_base::cur);
273 if(dataStart > 0 && format != AL_NONE)
274 fstream->seekg(dataStart);
278 struct aiffStream : public alureStream {
279 ALenum format;
280 int samplerate;
281 int blockAlign;
282 int sampleSize;
283 long dataStart;
284 long dataLen;
285 size_t remLen;
287 virtual bool IsValid()
288 { return (dataStart > 0 && format != AL_NONE); }
290 virtual bool GetFormat(ALenum *format, ALuint *frequency, ALuint *blockalign)
292 *format = this->format;
293 *frequency = samplerate;
294 *blockalign = blockAlign;
295 return true;
298 virtual ALuint GetData(ALubyte *data, ALuint bytes)
300 std::streamsize rem = ((remLen >= bytes) ? bytes : remLen) / blockAlign;
301 fstream->read(reinterpret_cast<char*>(data), rem*blockAlign);
303 std::streamsize got = fstream->gcount();
304 got -= got%blockAlign;
305 remLen -= got;
307 if(LittleEndian && sampleSize > 1)
309 if(sampleSize == 2)
310 for(std::streamsize i = 0;i < got;i+=2)
312 ALubyte tmp = data[i];
313 data[i] = data[i+1];
314 data[i+1] = tmp;
316 else if(sampleSize == 4)
317 for(std::streamsize i = 0;i < got;i+=4)
319 ALubyte tmp = data[i];
320 data[i] = data[i+3];
321 data[i+3] = tmp;
322 tmp = data[i+1];
323 data[i+1] = data[i+2];
324 data[i+2] = tmp;
328 return got;
331 virtual bool Rewind()
333 fstream->clear();
334 if(fstream->seekg(dataStart))
336 remLen = dataLen;
337 return true;
340 SetError("Seek failed");
341 return false;
344 aiffStream(std::istream *_fstream)
345 : alureStream(_fstream), format(0), dataStart(0)
346 { Init(); }
348 virtual ~aiffStream()
351 private:
352 void Init()
354 ALubyte buffer[25];
355 int length;
357 if(!fstream->read(reinterpret_cast<char*>(buffer), 12) ||
358 memcmp(buffer, "FORM", 4) != 0 || memcmp(buffer+8, "AIFF", 4) != 0)
359 return;
361 while(!dataStart || format == AL_NONE)
363 char tag[4];
364 if(!fstream->read(tag, 4))
365 break;
367 /* read chunk length */
368 length = read_be32(fstream);
370 if(memcmp(tag, "COMM", 4) == 0 && length >= 18)
372 /* mono or stereo data */
373 int channels = read_be16(fstream);
375 /* number of sample frames */
376 fstream->ignore(4);
378 /* bits per sample */
379 sampleSize = read_be16(fstream) / 8;
381 /* sample frequency */
382 samplerate = read_be80extended(fstream);
384 /* block alignment */
385 blockAlign = channels * sampleSize;
387 format = alureGetSampleFormat(channels, sampleSize*8, 0);
389 length -= 18;
391 else if(memcmp(tag, "SSND", 4) == 0)
393 dataStart = fstream->tellg();
394 dataStart += 8;
395 dataLen = remLen = length - 8;
398 fstream->seekg(length, std::ios_base::cur);
401 if(dataStart > 0 && format != AL_NONE)
402 fstream->seekg(dataStart);
406 #ifdef HAS_SNDFILE
407 struct sndStream : public alureStream {
408 SNDFILE *sndFile;
409 SF_INFO sndInfo;
411 virtual bool IsValid()
412 { return sndFile != NULL; }
414 virtual bool GetFormat(ALenum *format, ALuint *frequency, ALuint *blockalign)
416 *format = alureGetSampleFormat(sndInfo.channels, 16, 0);
417 *frequency = sndInfo.samplerate;
418 *blockalign = sndInfo.channels*2;
419 return true;
422 virtual ALuint GetData(ALubyte *data, ALuint bytes)
424 const ALuint frameSize = 2*sndInfo.channels;
425 return sf_readf_short(sndFile, (short*)data, bytes/frameSize) * frameSize;
428 virtual bool Rewind()
430 if(sf_seek(sndFile, 0, SEEK_SET) != -1)
431 return true;
433 SetError("Seek failed");
434 return false;
437 sndStream(std::istream *_fstream)
438 : alureStream(_fstream), sndFile(NULL)
440 memset(&sndInfo, 0, sizeof(sndInfo));
442 static SF_VIRTUAL_IO streamIO = {
443 get_filelen, seek,
444 read, write, tell
446 sndFile = sf_open_virtual(&streamIO, SFM_READ, &sndInfo, this);
449 virtual ~sndStream()
451 if(sndFile)
452 sf_close(sndFile);
453 sndFile = NULL;
456 private:
457 // libSndFile iostream callbacks
458 static sf_count_t get_filelen(void *user_data)
460 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
461 stream->clear();
463 std::streampos len = -1;
464 std::streampos pos = stream->tellg();
465 if(stream->seekg(0, std::ios_base::end))
467 len = stream->tellg();
468 stream->seekg(pos);
471 return len;
474 static sf_count_t seek(sf_count_t offset, int whence, void *user_data)
476 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
477 stream->clear();
479 if(whence == SEEK_CUR)
480 stream->seekg(offset, std::ios_base::cur);
481 else if(whence == SEEK_SET)
482 stream->seekg(offset, std::ios_base::beg);
483 else if(whence == SEEK_END)
484 stream->seekg(offset, std::ios_base::end);
485 else
486 return -1;
488 return stream->tellg();
491 static sf_count_t read(void *ptr, sf_count_t count, void *user_data)
493 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
494 stream->clear();
495 stream->read(static_cast<char*>(ptr), count);
496 return stream->gcount();
499 static sf_count_t write(const void*, sf_count_t, void*)
500 { return -1; }
502 static sf_count_t tell(void *user_data)
504 std::istream *stream = static_cast<sndStream*>(user_data)->fstream;
505 stream->clear();
506 return stream->tellg();
509 #else
510 struct sndStream : public nullStream {
511 sndStream(std::istream*){}
513 #endif
515 #ifdef HAS_VORBISFILE
516 struct oggStream : public alureStream {
517 OggVorbis_File *oggFile;
518 int oggBitstream;
520 virtual bool IsValid()
521 { return oggFile != NULL; }
523 virtual bool GetFormat(ALenum *format, ALuint *frequency, ALuint *blockalign)
525 vorbis_info *info = ov_info(oggFile, -1);
526 if(!info) return false;
528 *format = alureGetSampleFormat(info->channels, 16, 0);
529 *frequency = info->rate;
530 *blockalign = info->channels*2;
531 return true;
534 virtual ALuint GetData(ALubyte *data, ALuint bytes)
536 int got = 0;
537 while(bytes > 0)
539 int res = ov_read(oggFile, (char*)&data[got], bytes, BigEndian?1:0, 2, 1, &oggBitstream);
540 if(res <= 0)
541 break;
542 bytes -= res;
543 got += res;
545 return got;
548 virtual bool Rewind()
550 if(ov_pcm_seek(oggFile, 0) == 0)
551 return true;
553 SetError("Seek failed");
554 return false;
557 oggStream(std::istream *_fstream)
558 : alureStream(_fstream), oggFile(NULL), oggBitstream(0)
560 const ov_callbacks streamIO = {
561 read, seek, NULL, tell
564 oggFile = new OggVorbis_File;
565 if(ov_open_callbacks(this, oggFile, NULL, 0, streamIO) != 0)
567 delete oggFile;
568 oggFile = NULL;
572 virtual ~oggStream()
574 if(oggFile)
576 ov_clear(oggFile);
577 delete oggFile;
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 #else
618 struct oggStream : public nullStream {
619 oggStream(std::istream*){}
621 #endif
623 #ifdef HAS_FLAC
624 struct flacStream : public alureStream {
625 FLAC__StreamDecoder *flacFile;
626 ALenum format;
627 ALuint samplerate;
628 ALuint blockAlign;
629 ALboolean useFloat;
631 std::vector<ALubyte> initialData;
633 ALubyte *outBytes;
634 ALuint outLen;
635 ALuint outTotal;
637 virtual bool IsValid()
638 { return flacFile != NULL; }
640 virtual bool GetFormat(ALenum *format, ALuint *frequency, ALuint *blockalign)
642 *format = this->format;
643 *frequency = samplerate;
644 *blockalign = blockAlign;
645 return true;
648 virtual ALuint GetData(ALubyte *data, ALuint bytes)
650 outBytes = data;
651 outTotal = 0;
652 outLen = bytes;
654 if(initialData.size() > 0)
656 size_t rem = std::min(initialData.size(), (size_t)bytes);
657 memcpy(data, &initialData[0], rem);
658 outTotal += rem;
659 initialData.erase(initialData.begin(), initialData.begin()+rem);
662 while(outTotal < bytes)
664 if(FLAC__stream_decoder_process_single(flacFile) == false ||
665 FLAC__stream_decoder_get_state(flacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
666 break;
669 return outTotal;
672 virtual bool Rewind()
674 if(FLAC__stream_decoder_seek_absolute(flacFile, 0) != false)
676 initialData.clear();
677 return true;
680 SetError("Seek failed");
681 return false;
684 flacStream(std::istream *_fstream)
685 : alureStream(_fstream), flacFile(NULL), format(AL_NONE), samplerate(0),
686 blockAlign(0), useFloat(AL_FALSE)
688 flacFile = FLAC__stream_decoder_new();
689 if(flacFile)
691 if(FLAC__stream_decoder_init_stream(flacFile, ReadCallback, SeekCallback, TellCallback, LengthCallback, EofCallback, WriteCallback, MetadataCallback, ErrorCallback, this) == FLAC__STREAM_DECODER_INIT_STATUS_OK)
693 if(InitFlac())
695 // all ok
696 return;
699 FLAC__stream_decoder_finish(flacFile);
701 FLAC__stream_decoder_delete(flacFile);
702 flacFile = NULL;
706 virtual ~flacStream()
708 if(flacFile)
710 FLAC__stream_decoder_finish(flacFile);
711 FLAC__stream_decoder_delete(flacFile);
712 flacFile = NULL;
716 private:
717 bool InitFlac()
719 // We need to decode some data to be able to get the channel count, bit
720 // depth, and sample rate. It also ensures the file has FLAC data, as
721 // the FLAC__stream_decoder_init_* functions can succeed on non-FLAC
722 // Ogg files.
723 outLen = 0;
724 outTotal = 0;
725 while(initialData.size() == 0)
727 if(FLAC__stream_decoder_process_single(flacFile) == false ||
728 FLAC__stream_decoder_get_state(flacFile) == FLAC__STREAM_DECODER_END_OF_STREAM)
729 break;
732 if(initialData.size() > 0)
733 return true;
734 return false;
737 static FLAC__StreamDecoderWriteStatus WriteCallback(const FLAC__StreamDecoder*, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
739 flacStream *This = static_cast<flacStream*>(client_data);
740 ALubyte *data = This->outBytes + This->outTotal;
741 ALuint i = 0;
743 if(This->format == AL_NONE)
745 ALuint bps = frame->header.bits_per_sample;
746 if(bps == 24 || bps == 32)
748 This->format = alureGetSampleFormat(frame->header.channels, 0, 32);
749 if(This->format != AL_NONE)
751 This->useFloat = AL_TRUE;
752 bps = 32;
754 else bps = 16;
756 if(This->format == AL_NONE)
757 This->format = alureGetSampleFormat(frame->header.channels, bps, 0);
758 This->blockAlign = frame->header.channels * bps/8;
759 This->samplerate = frame->header.sample_rate;
762 const ALboolean useFloat = This->useFloat;
763 while(This->outTotal < This->outLen && i < frame->header.blocksize)
765 for(ALuint c = 0;c < frame->header.channels;c++)
767 if(frame->header.bits_per_sample == 8)
768 ((ALubyte*)data)[c] = buffer[c][i]+128;
769 else if(frame->header.bits_per_sample == 16)
770 ((ALshort*)data)[c] = buffer[c][i];
771 else if(frame->header.bits_per_sample == 24)
773 if(useFloat)
774 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
775 buffer[c][i]/(float)0x7FFFFF :
776 buffer[c][i]/(float)0x800000);
777 else
778 ((ALshort*)data)[c] = buffer[c][i]>>8;
780 else if(frame->header.bits_per_sample == 32)
782 if(useFloat)
783 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
784 buffer[c][i]/(float)0x7FFFFFFF :
785 buffer[c][i]/(float)0x80000000u);
786 else
787 ((ALshort*)data)[c] = buffer[c][i]>>16;
790 This->outTotal += This->blockAlign;
791 data += This->blockAlign;
792 i++;
795 if(i < frame->header.blocksize)
797 ALuint blocklen = (frame->header.blocksize-i) *
798 This->blockAlign;
799 ALuint start = This->initialData.size();
801 This->initialData.resize(start+blocklen);
802 data = &This->initialData[start];
804 do {
805 for(ALuint c = 0;c < frame->header.channels;c++)
807 if(frame->header.bits_per_sample == 8)
808 ((ALubyte*)data)[c] = buffer[c][i]+128;
809 else if(frame->header.bits_per_sample == 16)
810 ((ALshort*)data)[c] = buffer[c][i];
811 else if(frame->header.bits_per_sample == 24)
813 if(useFloat)
814 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
815 buffer[c][i]/(float)0x7FFFFF :
816 buffer[c][i]/(float)0x800000);
817 else
818 ((ALshort*)data)[c] = buffer[c][i]>>8;
820 else if(frame->header.bits_per_sample == 32)
822 if(useFloat)
823 ((ALfloat*)data)[c] = ((buffer[c][i]>=0) ?
824 buffer[c][i]/(float)0x7FFFFFFF :
825 buffer[c][i]/(float)0x80000000u);
826 else
827 ((ALshort*)data)[c] = buffer[c][i]>>16;
830 data += This->blockAlign;
831 i++;
832 } while(i < frame->header.blocksize);
835 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
837 static void MetadataCallback(const FLAC__StreamDecoder*,const FLAC__StreamMetadata*,void*)
840 static void ErrorCallback(const FLAC__StreamDecoder*,FLAC__StreamDecoderErrorStatus,void*)
844 static FLAC__StreamDecoderReadStatus ReadCallback(const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t *bytes, void *client_data)
846 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
847 stream->clear();
849 if(*bytes <= 0)
850 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
852 stream->read(reinterpret_cast<char*>(buffer), *bytes);
853 *bytes = stream->gcount();
854 if(*bytes == 0 && stream->eof())
855 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
857 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
859 static FLAC__StreamDecoderSeekStatus SeekCallback(const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void *client_data)
861 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
862 stream->clear();
864 if(!stream->seekg(absolute_byte_offset))
865 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
866 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
868 static FLAC__StreamDecoderTellStatus TellCallback(const FLAC__StreamDecoder*, FLAC__uint64 *absolute_byte_offset, void *client_data)
870 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
871 stream->clear();
873 *absolute_byte_offset = stream->tellg();
874 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
876 static FLAC__StreamDecoderLengthStatus LengthCallback(const FLAC__StreamDecoder*, FLAC__uint64 *stream_length, void *client_data)
878 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
879 stream->clear();
881 std::streampos pos = stream->tellg();
882 if(stream->seekg(0, std::ios_base::end))
884 *stream_length = stream->tellg();
885 stream->seekg(pos);
888 if(!stream->good())
889 return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR;
890 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
892 static FLAC__bool EofCallback(const FLAC__StreamDecoder*, void *client_data)
894 std::istream *stream = static_cast<flacStream*>(client_data)->fstream;
895 return (stream->eof()) ? true : false;
898 #else
899 struct flacStream : public nullStream {
900 flacStream(std::istream*){}
902 #endif
905 #ifdef HAS_MPG123
906 struct mp3Stream : public alureStream {
907 mpg123_handle *mp3File;
908 long samplerate;
909 int channels;
911 virtual bool IsValid()
912 { return mp3File != NULL; }
914 virtual bool GetFormat(ALenum *format, ALuint *frequency, ALuint *blockalign)
916 ALenum fmt = alureGetSampleFormat(channels, 16, 0);
918 *format = fmt;
919 *frequency = samplerate;
920 *blockalign = channels*2;
921 return true;
924 virtual ALuint GetData(ALubyte *data, ALuint bytes)
926 ALuint amt = 0;
927 while(bytes > 0)
929 size_t got = 0;
930 int ret = mpg123_read(mp3File, data, bytes, &got);
932 bytes -= got;
933 data += got;
934 amt += got;
936 if(ret == MPG123_NEW_FORMAT)
938 long newrate;
939 int newchans, enc;
940 mpg123_getformat(mp3File, &newrate, &newchans, &enc);
942 if(ret == MPG123_NEED_MORE)
944 unsigned char data[4096];
945 fstream->read((char*)data, sizeof(data));
946 std::streamsize insize = fstream->gcount();
947 if(insize > 0 && mpg123_feed(mp3File, data, insize) == MPG123_OK)
948 continue;
950 if(got == 0)
951 break;
953 return amt;
956 virtual bool Rewind()
958 fstream->clear();
959 std::istream::pos_type oldpos = fstream->tellg();
960 fstream->seekg(0);
962 mpg123_handle *newFile = mpg123_new(NULL, NULL);
963 if(mpg123_open_feed(newFile) == MPG123_OK)
965 unsigned char data[4096];
966 long newrate;
967 int newchans;
968 int ret, enc;
970 ALuint amt, total = 0;
971 do {
972 fstream->read((char*)data, sizeof(data));
973 amt = fstream->gcount();
974 if(amt == 0) break;
975 total += amt;
976 ret = mpg123_decode(newFile, data, amt, NULL, 0, NULL);
977 } while(ret == MPG123_NEED_MORE && total < 64*1024);
979 if(ret == MPG123_NEW_FORMAT &&
980 mpg123_getformat(newFile, &newrate, &newchans, &enc) == MPG123_OK)
982 if(mpg123_format_none(newFile) == MPG123_OK &&
983 mpg123_format(newFile, samplerate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK)
985 // All OK
986 mpg123_delete(mp3File);
987 mp3File = newFile;
988 return true;
991 mpg123_delete(newFile);
994 fstream->seekg(oldpos);
995 SetError("Restart failed");
996 return false;
999 mp3Stream(std::istream *_fstream)
1000 : alureStream(_fstream), mp3File(NULL)
1002 mp3File = mpg123_new(NULL, NULL);
1003 if(mpg123_open_feed(mp3File) == MPG123_OK)
1005 unsigned char data[4096];
1006 int ret, enc;
1008 ALuint amt, total = 0;
1009 do {
1010 fstream->read((char*)data, sizeof(data));
1011 amt = fstream->gcount();
1012 if(amt == 0) break;
1013 total += amt;
1014 ret = mpg123_decode(mp3File, data, amt, NULL, 0, NULL);
1015 } while(ret == MPG123_NEED_MORE && total < 64*1024);
1017 if(ret == MPG123_NEW_FORMAT &&
1018 mpg123_getformat(mp3File, &samplerate, &channels, &enc) == MPG123_OK)
1020 if(mpg123_format_none(mp3File) == MPG123_OK &&
1021 mpg123_format(mp3File, samplerate, channels, MPG123_ENC_SIGNED_16) == MPG123_OK)
1023 // All OK
1024 return;
1028 mpg123_delete(mp3File);
1029 mp3File = NULL;
1032 virtual ~mp3Stream()
1034 if(mp3File)
1035 mpg123_delete(mp3File);
1036 mp3File = NULL;
1039 #else
1040 struct mp3Stream : public nullStream {
1041 mp3Stream(std::istream*){}
1043 #endif
1046 #ifdef HAS_DUMB
1047 struct dumbStream : public alureStream {
1048 DUMBFILE_SYSTEM vfs;
1049 DUMBFILE *dumbFile;
1050 DUH *duh;
1051 DUH_SIGRENDERER *renderer;
1052 std::vector<sample_t> sampleBuf;
1053 ALuint lastOrder;
1054 int prevSpeed;
1055 ALenum format;
1057 virtual bool IsValid()
1058 { return renderer != NULL; }
1060 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
1062 if(format == AL_NONE)
1064 format = alureGetSampleFormat(2, 0, 32);
1065 if(format == AL_NONE)
1066 format = AL_FORMAT_STEREO16;
1068 *fmt = format;
1069 *frequency = 65536;
1070 *blockalign = 2 * ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) :
1071 sizeof(ALfloat));
1072 return true;
1075 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1077 ALuint ret = 0;
1079 if(dumb_it_sr_get_speed(duh_get_it_sigrenderer(renderer)) == 0)
1080 return 0;
1082 ALuint sample_count = bytes / ((format==AL_FORMAT_STEREO16) ?
1083 sizeof(ALshort) : sizeof(ALfloat));
1085 sampleBuf.resize(sample_count);
1086 sample_t *samples = &sampleBuf[0];
1088 dumb_silence(samples, sample_count);
1089 ret = duh_sigrenderer_generate_samples(renderer, 1.0f, 1.0f, sample_count/2, &samples);
1090 ret *= 2;
1091 if(format == AL_FORMAT_STEREO16)
1093 for(ALuint i = 0;i < ret;i++)
1094 ((ALshort*)data)[i] = clamp(samples[i]>>8, -32768, 32767);
1096 else
1098 for(ALuint i = 0;i < ret;i++)
1099 ((ALfloat*)data)[i] = ((samples[i]>=0) ?
1100 samples[i]/(float)0x7FFFFF :
1101 samples[i]/(float)0x800000);
1103 ret *= ((format==AL_FORMAT_STEREO16) ? sizeof(ALshort) : sizeof(ALfloat));
1105 return ret;
1108 virtual bool Rewind()
1110 if(prevSpeed)
1112 // If a previous speed was recorded, the stream tried to loop. So
1113 // let it loop on a rewind request.
1114 dumb_it_sr_set_speed(duh_get_it_sigrenderer(renderer), prevSpeed);
1115 prevSpeed = 0;
1116 return true;
1119 // Else, no loop point. Restart from scratch.
1120 DUH_SIGRENDERER *newrenderer;
1121 newrenderer = (lastOrder ? dumb_it_start_at_order(duh, 2, lastOrder) :
1122 duh_start_sigrenderer(duh, 0, 2, 0));
1123 if(!newrenderer)
1125 SetError("Could start renderer");
1126 return false;
1128 duh_end_sigrenderer(renderer);
1129 renderer = newrenderer;
1130 return true;
1133 virtual bool SetOrder(ALuint order)
1135 DUH_SIGRENDERER *newrenderer = dumb_it_start_at_order(duh, 2, order);
1136 if(!newrenderer)
1138 SetError("Could not set order");
1139 return false;
1141 duh_end_sigrenderer(renderer);
1142 renderer = newrenderer;
1144 lastOrder = order;
1145 return true;
1148 dumbStream(std::istream *_fstream)
1149 : alureStream(_fstream), dumbFile(NULL), duh(NULL), renderer(NULL),
1150 lastOrder(0), prevSpeed(0), format(AL_NONE)
1152 DUH* (*funcs[])(DUMBFILE*) = {
1153 dumb_read_it_quick,
1154 dumb_read_xm_quick,
1155 dumb_read_s3m_quick,
1156 dumb_read_mod_quick,
1157 NULL
1160 vfs.open = NULL;
1161 vfs.skip = skip;
1162 vfs.getc = read_char;
1163 vfs.getnc = read;
1164 vfs.close = NULL;
1166 for(size_t i = 0;funcs[i];i++)
1168 dumbFile = dumbfile_open_ex(this, &vfs);
1169 if(dumbFile)
1171 duh = funcs[i](dumbFile);
1172 if(duh)
1174 renderer = duh_start_sigrenderer(duh, 0, 2, 0);
1175 if(renderer)
1177 dumb_it_set_loop_callback(duh_get_it_sigrenderer(renderer), loop_cb, this);
1178 break;
1181 unload_duh(duh);
1182 duh = NULL;
1185 dumbfile_close(dumbFile);
1186 dumbFile = NULL;
1188 fstream->clear();
1189 fstream->seekg(0);
1193 virtual ~dumbStream()
1195 duh_end_sigrenderer(renderer);
1196 renderer = NULL;
1198 unload_duh(duh);
1199 duh = NULL;
1201 if(dumbFile)
1202 dumbfile_close(dumbFile);
1203 dumbFile = NULL;
1206 private:
1207 // DUMBFILE iostream callbacks
1208 static int skip(void *user_data, long offset)
1210 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1211 stream->clear();
1213 if(stream->seekg(offset, std::ios_base::cur))
1214 return 0;
1215 return -1;
1218 static long read(char *ptr, long size, void *user_data)
1220 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1221 stream->clear();
1223 stream->read(static_cast<char*>(ptr), size);
1224 return stream->gcount();
1227 static int read_char(void *user_data)
1229 std::istream *stream = static_cast<dumbStream*>(user_data)->fstream;
1230 stream->clear();
1232 unsigned char ret;
1233 stream->read(reinterpret_cast<char*>(&ret), 1);
1234 if(stream->gcount() > 0)
1235 return ret;
1236 return -1;
1239 static int loop_cb(void *user_data)
1241 dumbStream *This = static_cast<dumbStream*>(user_data);
1242 This->prevSpeed = dumb_it_sr_get_speed(duh_get_it_sigrenderer(This->renderer));
1243 dumb_it_sr_set_speed(duh_get_it_sigrenderer(This->renderer), 0);
1244 return 0;
1247 #else
1248 struct dumbStream : public nullStream {
1249 dumbStream(std::istream*){}
1251 #endif
1254 #ifdef HAS_TIMIDITY
1255 struct midiStream : public alureStream {
1256 int pcmFile;
1257 pid_t cpid;
1259 static const ALuint Freq = 48000;
1261 virtual bool IsValid()
1262 { return cpid > 0; }
1264 virtual bool GetFormat(ALenum *fmt, ALuint *frequency, ALuint *blockalign)
1266 *fmt = AL_FORMAT_STEREO16;
1267 *frequency = Freq;
1268 *blockalign = 4;
1269 return true;
1272 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1274 ALuint total = 0;
1275 while(bytes > 0)
1277 ssize_t got;
1278 while((got=read(pcmFile, &data[total], bytes)) == -1 && errno == EINTR)
1280 if(got <= 0)
1281 break;
1282 bytes -= got;
1283 total += got;
1286 if(BigEndian)
1288 for(ALuint i = 0;i < total;i+=2)
1290 ALubyte tmp = data[i];
1291 data[i] = data[i+1];
1292 data[i+1] = tmp;
1296 return total;
1299 virtual bool Rewind()
1301 fstream->clear();
1302 fstream->seekg(0);
1304 int _pcmFile; pid_t _cpid;
1305 if(!StartStream(_pcmFile, _cpid))
1307 SetError("Failed to restart timidity");
1308 return false;
1311 kill(cpid, SIGTERM);
1312 waitpid(cpid, NULL, 0);
1313 cpid = _cpid;
1315 close(pcmFile);
1316 pcmFile = _pcmFile;
1318 return true;
1321 midiStream(std::istream *_fstream)
1322 : alureStream(_fstream), pcmFile(-1), cpid(-1)
1324 StartStream(pcmFile, cpid);
1327 virtual ~midiStream()
1329 if(cpid > 0)
1331 kill(cpid, SIGTERM);
1332 waitpid(cpid, NULL, 0);
1333 cpid = -1;
1335 if(pcmFile != -1)
1336 close(pcmFile);
1337 pcmFile = -1;
1340 private:
1341 bool StartStream(int &pcmFile, pid_t &cpid)
1343 char hdr[4];
1344 std::vector<ALubyte> midiData;
1346 fstream->read(hdr, sizeof(hdr));
1347 if(fstream->gcount() != sizeof(hdr))
1348 return false;
1350 if(memcmp(hdr, "MThd", 4) == 0)
1352 char ch;
1353 for(size_t i = 0;i < sizeof(hdr);i++)
1354 midiData.push_back(hdr[i]);
1355 while(fstream->get(ch))
1356 midiData.push_back(ch);
1358 else if(memcmp(hdr, "MUS\x1a", sizeof(hdr)) == 0)
1360 if(!ConvertMUS(midiData))
1361 return false;
1363 else
1364 return false;
1366 int midPipe[2], pcmPipe[2];
1367 if(pipe(midPipe) == -1)
1368 return false;
1369 if(pipe(pcmPipe) == -1)
1371 close(midPipe[0]);
1372 close(midPipe[1]);
1373 return false;
1376 pid_t pid = fork();
1377 if(pid < 0)
1379 close(midPipe[0]);
1380 close(midPipe[1]);
1381 close(pcmPipe[0]);
1382 close(pcmPipe[1]);
1383 return false;
1386 if(pid == 0)
1388 if(dup2(midPipe[0], STDIN_FILENO) != -1 &&
1389 dup2(pcmPipe[1], STDOUT_FILENO) != -1)
1391 close(midPipe[0]);
1392 close(midPipe[1]);
1393 close(pcmPipe[0]);
1394 close(pcmPipe[1]);
1396 std::stringstream freqstr;
1397 freqstr << Freq;
1399 execlp("timidity","timidity","-","-idqq","-Ow1sl","-o","-",
1400 "-s", freqstr.str().c_str(), NULL);
1402 _exit(1);
1405 close(midPipe[0]); midPipe[0] = -1;
1406 close(pcmPipe[1]); pcmPipe[1] = -1;
1408 void (*oldhandler)(int) = signal(SIGPIPE, SIG_IGN);
1409 ALubyte *cur = &midiData[0];
1410 size_t rem = midiData.size();
1411 do {
1412 ssize_t wrote;
1413 while((wrote=write(midPipe[1], cur, rem)) == -1 && errno == EINTR)
1415 if(wrote <= 0)
1416 break;
1417 cur += wrote;
1418 rem -= wrote;
1419 } while(rem > 0);
1420 close(midPipe[1]); midPipe[1] = -1;
1421 signal(SIGPIPE, oldhandler);
1423 ALubyte fmthdr[44];
1424 cur = fmthdr;
1425 rem = sizeof(fmthdr);
1426 do {
1427 ssize_t got;
1428 while((got=read(pcmPipe[0], cur, rem)) == -1 && errno == EINTR)
1430 if(got <= 0)
1431 break;
1432 cur += got;
1433 rem -= got;
1434 } while(rem > 0);
1435 if(rem > 0)
1437 kill(pid, SIGTERM);
1438 waitpid(pid, NULL, 0);
1439 close(pcmPipe[0]);
1440 return false;
1443 pcmFile = pcmPipe[0];
1444 cpid = pid;
1445 return true;
1448 alureUInt64 ReadVarLen()
1450 alureUInt64 val = 0;
1451 char ch;
1453 do {
1454 if(!fstream->get(ch))
1455 break;
1456 val = (val<<7) | (ch&0x7f);
1457 } while((ch&0x80));
1459 return val;
1462 void WriteVarLen(std::vector<ALubyte> &out, alureUInt64 val)
1464 alureUInt64 buffer = val&0x7f;
1465 while((val>>=7) > 0)
1466 buffer = (buffer<<8) | 0x80 | (val&0x7f);
1467 while(1)
1469 out.push_back(buffer&0xff);
1470 if(!(buffer&0x80))
1471 break;
1472 buffer >>= 8;
1476 static const ALubyte MIDI_SYSEX = 0xF0; // SysEx begin
1477 static const ALubyte MIDI_SYSEXEND = 0xF7; // SysEx end
1478 static const ALubyte MIDI_META = 0xFF; // Meta event begin
1479 static const ALubyte MIDI_META_TEMPO = 0x51;
1480 static const ALubyte MIDI_META_EOT = 0x2F; // End-of-track
1481 static const ALubyte MIDI_META_SSPEC = 0x7F; // System-specific event
1483 static const ALubyte MIDI_NOTEOFF = 0x80; // + note + velocity
1484 static const ALubyte MIDI_NOTEON = 0x90; // + note + velocity
1485 static const ALubyte MIDI_POLYPRESS = 0xA0; // + pressure (2 bytes)
1486 static const ALubyte MIDI_CTRLCHANGE = 0xB0; // + ctrlr + value
1487 static const ALubyte MIDI_PRGMCHANGE = 0xC0; // + new patch
1488 static const ALubyte MIDI_CHANPRESS = 0xD0; // + pressure (1 byte)
1489 static const ALubyte MIDI_PITCHBEND = 0xE0; // + pitch bend (2 bytes)
1491 static const ALubyte MUS_EVENT_CHANNEL_MASK = 0x0F;
1492 static const ALubyte MUS_EVENT_DELTA_MASK = 0x80;
1494 static const ALubyte MUS_NOTEOFF = 0x00;
1495 static const ALubyte MUS_NOTEON = 0x10;
1496 static const ALubyte MUS_PITCHBEND = 0x20;
1497 static const ALubyte MUS_SYSEVENT = 0x30;
1498 static const ALubyte MUS_CTRLCHANGE = 0x40;
1499 static const ALubyte MUS_SCOREEND = 0x60;
1501 bool ConvertMUS(std::vector<ALubyte> &midiData)
1503 static const ALubyte CtrlTranslate[15] = {
1504 0, // program change
1505 0, // bank select
1506 1, // modulation pot
1507 7, // volume
1508 10, // pan pot
1509 11, // expression pot
1510 91, // reverb depth
1511 93, // chorus depth
1512 64, // sustain pedal
1513 67, // soft pedal
1514 120, // all sounds off
1515 123, // all notes off
1516 126, // mono
1517 127, // poly
1518 121 // reset all controllers
1521 static const ALubyte MIDIhead[22] = {
1522 'M','T','h','d', 0, 0, 0, 6,
1523 0, 0, // format 0: only one track
1524 0, 1, // yes, there is really only one track
1525 0, 70, // 70 divisions
1526 'M','T','r','k', 0xFF, 0xFF, 0xFF, 0xFF
1529 // The MUS\x1a ID was already read and verified
1530 ALushort songLen = read_le16(fstream);
1531 ALushort songStart = read_le16(fstream);
1532 ALushort numChans = read_le16(fstream);
1534 // Sanity check the MUS file's channel count
1535 if(numChans > 15)
1536 return false;
1538 fstream->seekg(songStart);
1539 std::streamsize maxmus_p = songLen;
1540 maxmus_p += fstream->tellg();
1542 ALubyte chanVel[16];
1543 for(size_t i = 0;i < 16;i++)
1544 chanVel[i] = 100;
1546 bool firstUse[16];
1547 for(size_t i = 0;i < 16;i++)
1548 firstUse[i] = true;
1550 alureUInt64 deltaTime = 0;
1551 ALubyte event = 0;
1552 ALubyte status = 0;
1554 // Setup header
1555 for(size_t i = 0;i < sizeof(MIDIhead);i++)
1556 midiData.push_back(MIDIhead[i]);
1558 // The first event sets the tempo to 500,000 microsec/quarter note
1559 midiData.push_back(0);
1560 midiData.push_back(MIDI_META | 0);
1561 midiData.push_back(MIDI_META_TEMPO | 0);
1562 midiData.push_back(3);
1563 midiData.push_back(0x07);
1564 midiData.push_back(0xA1);
1565 midiData.push_back(0x20);
1567 while(fstream->good() && fstream->tellg() < maxmus_p && event != MUS_SCOREEND)
1569 event = fstream->get();
1571 bool hasDelta = event&MUS_EVENT_DELTA_MASK;
1572 ALubyte channel = event&MUS_EVENT_CHANNEL_MASK;
1574 event &= ~MUS_EVENT_DELTA_MASK;
1575 event &= ~MUS_EVENT_CHANNEL_MASK;
1577 // Convert percussion channel (MUS #15 -> MIDI #9)
1578 if(channel == 15)
1579 channel = 9;
1580 else if(channel >= 9)
1581 channel++;
1583 if(firstUse[channel])
1585 // This is the first time this channel has been used,
1586 // so sets its volume to 127.
1587 firstUse[channel] = false;
1588 midiData.push_back(0);
1589 midiData.push_back(MIDI_CTRLCHANGE | channel);
1590 midiData.push_back(7);
1591 midiData.push_back(127);
1594 ALubyte t = 0;
1595 if(event != MUS_SCOREEND)
1596 t = fstream->get();
1598 ALubyte midArgs = 2;
1599 ALubyte midStatus = channel;
1600 ALubyte mid1 = 0, mid2 = 0;
1601 bool noop = false;
1603 switch(event)
1605 case MUS_NOTEOFF:
1606 midStatus |= MIDI_NOTEOFF;
1607 mid1 = t&0x7f;
1608 mid2 = 64;
1609 break;
1611 case MUS_NOTEON:
1612 midStatus |= MIDI_NOTEON;
1613 mid1 = t&0x7f;
1614 if((t&0x80))
1615 chanVel[channel] = fstream->get()&0x7f;
1616 mid2 = chanVel[channel];
1617 break;
1619 case MUS_PITCHBEND:
1620 midStatus |= MIDI_PITCHBEND;
1621 mid1 = (t&1) << 6;
1622 mid2 = (t>>1) & 0x7f;
1623 break;
1625 case MUS_SYSEVENT:
1626 if(t < 10 || t > 14)
1627 noop = true;
1628 else
1630 midStatus |= MIDI_CTRLCHANGE;
1631 mid1 = CtrlTranslate[t];
1632 mid2 = ((t==12) /* Mono */ ? numChans : 0);
1634 break;
1636 case MUS_CTRLCHANGE:
1637 if(t == 0)
1639 // Program change, only one arg
1640 midArgs = 1;
1641 midStatus |= MIDI_PRGMCHANGE;
1642 mid1 = fstream->get()&0x7f;
1644 else if(t < 10)
1646 midStatus |= MIDI_CTRLCHANGE;
1647 mid1 = CtrlTranslate[t];
1648 mid2 = fstream->get();
1650 else
1651 noop = true;
1652 break;
1654 case MUS_SCOREEND:
1655 midStatus = MIDI_META;
1656 mid1 = MIDI_META_EOT;
1657 mid2 = 0;
1658 break;
1660 default:
1661 return false;
1664 if(noop)
1666 // A system-specific event with no data is a no-op.
1667 midStatus = MIDI_META;
1668 mid1 = MIDI_META_SSPEC;
1669 mid2 = 0;
1672 WriteVarLen(midiData, deltaTime);
1673 if(midStatus != status)
1675 status = midStatus;
1676 midiData.push_back(status);
1678 if(midArgs >= 1)
1679 midiData.push_back(mid1);
1680 if(midArgs >= 2)
1681 midiData.push_back(mid2);
1683 deltaTime = (hasDelta ? ReadVarLen() : 0);
1686 // If reading failed or we overran the song length, the song is bad
1687 if(!fstream->good() || fstream->tellg() > maxmus_p)
1688 return false;
1690 // Fill in track length
1691 size_t trackLen = midiData.size() - 22;
1692 midiData[18] = (trackLen>>24) & 0xff;
1693 midiData[19] = (trackLen>>16) & 0xff;
1694 midiData[20] = (trackLen>>8) & 0xff;
1695 midiData[21] = trackLen&0xff;
1696 return true;
1699 #else
1700 struct midiStream : public nullStream {
1701 midiStream(std::istream*){}
1703 #endif
1706 #ifdef HAS_GSTREAMER
1707 struct gstStream : public alureStream {
1708 GstElement *gstPipeline;
1710 ALenum format;
1711 ALuint samplerate;
1712 ALuint blockAlign;
1714 std::vector<ALubyte> initialData;
1716 ALubyte *outBytes;
1717 ALuint outLen;
1718 ALuint outTotal;
1720 virtual bool IsValid()
1721 { return gstPipeline != NULL; }
1723 virtual bool GetFormat(ALenum *format, ALuint *frequency, ALuint *blockalign)
1725 *format = this->format;
1726 *frequency = samplerate;
1727 *blockalign = blockAlign;
1728 return true;
1731 virtual ALuint GetData(ALubyte *data, ALuint bytes)
1733 outTotal = 0;
1734 outLen = bytes;
1735 outBytes = data;
1737 if(initialData.size() > 0)
1739 size_t rem = std::min(initialData.size(), (size_t)bytes);
1740 memcpy(data, &initialData[0], rem);
1741 outTotal += rem;
1742 initialData.erase(initialData.begin(), initialData.begin()+rem);
1745 GstElement *gstSink = gst_bin_get_by_name(GST_BIN(gstPipeline), "alureSink");
1746 while(outTotal < outLen && !gst_app_sink_is_eos((GstAppSink*)gstSink))
1747 on_new_buffer_from_source(gstSink);
1748 gst_object_unref(gstSink);
1750 return outTotal;
1753 virtual bool Rewind()
1755 GstSeekFlags flags = GstSeekFlags(GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_KEY_UNIT);
1756 if(gst_element_seek_simple(gstPipeline, GST_FORMAT_TIME, flags, 0))
1758 initialData.clear();
1759 return true;
1762 SetError("Seek failed");
1763 return false;
1766 gstStream(std::istream *_fstream)
1767 : alureStream(_fstream), gstPipeline(NULL), format(AL_NONE), outBytes(NULL),
1768 outLen(0), outTotal(0)
1769 { Init(); }
1771 virtual ~gstStream()
1773 if(gstPipeline)
1775 gst_element_set_state(gstPipeline, GST_STATE_NULL);
1776 gst_object_unref(gstPipeline);
1777 gstPipeline = NULL;
1781 private:
1782 void Init()
1784 fstream->seekg(0, std::ios_base::end);
1785 std::streamsize len = fstream->tellg();
1786 fstream->seekg(0, std::ios_base::beg);
1788 if(!fstream->good() || len <= 0)
1789 return;
1791 std::string gst_audio_caps;
1792 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
1794 static const struct {
1795 const char *ename;
1796 const char *chans;
1797 const char *order;
1798 } fmts32[] = {
1799 { "AL_FORMAT_71CHN32", "8", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT" },
1800 { "AL_FORMAT_51CHN32", "6", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT" },
1801 { "AL_FORMAT_QUAD32", "4", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT" },
1802 { "AL_FORMAT_STEREO_FLOAT32", "2", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT" },
1803 { "AL_FORMAT_MONO_FLOAT32", "1", "GST_AUDIO_CHANNEL_POSITION_FRONT_MONO" },
1804 { NULL, NULL, NULL }
1805 }, fmts16[] = {
1806 { "AL_FORMAT_71CHN16", "8", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT" },
1807 { "AL_FORMAT_51CHN16", "6", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT" },
1808 { "AL_FORMAT_QUAD16", "4", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT" },
1809 { "AL_FORMAT_STEREO16", "2", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT" },
1810 { "AL_FORMAT_MONO16", "1", "GST_AUDIO_CHANNEL_POSITION_FRONT_MONO" },
1811 { NULL, NULL, NULL }
1812 }, fmts8[] = {
1813 { "AL_FORMAT_71CHN8", "8", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT" },
1814 { "AL_FORMAT_51CHN8", "6", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_LFE, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT" },
1815 { "AL_FORMAT_QUAD8", "4", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT" },
1816 { "AL_FORMAT_STEREO8", "2", "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT" },
1817 { "AL_FORMAT_MONO8", "1", "GST_AUDIO_CHANNEL_POSITION_FRONT_MONO" },
1818 { NULL, NULL, NULL }
1821 if(alIsExtensionPresent("AL_EXT_FLOAT32"))
1823 for(int i = 0;fmts32[i].ename;i++)
1825 if(alGetEnumValue(fmts32[i].ename) == 0)
1826 continue;
1828 gst_audio_caps +=
1829 "audio/x-raw-float, \n\t"
1830 "endianness = (int) { " G_STRINGIFY(G_BYTE_ORDER) " }, \n\t"
1831 "signed = (boolean) TRUE, \n\t"
1832 "width = (int) 32, \n\t"
1833 "depth = (int) 32, \n\t"
1834 "rate = (int) [ 1, MAX ], \n\t"
1835 "channels = (int) ";
1836 gst_audio_caps += fmts32[i].chans;
1837 gst_audio_caps += ", \n\t"
1838 "channel-positions = (GstAudioChannelPosition) < ";
1839 gst_audio_caps += fmts32[i].order;
1840 gst_audio_caps += " >; \n";
1843 for(int i = 0;fmts16[i].ename;i++)
1845 if(alGetEnumValue(fmts16[i].ename) == 0)
1846 continue;
1848 gst_audio_caps +=
1849 "audio/x-raw-int, \n\t"
1850 "endianness = (int) { " G_STRINGIFY(G_BYTE_ORDER) " }, \n\t"
1851 "signed = (boolean) TRUE, \n\t"
1852 "width = (int) 16, \n\t"
1853 "depth = (int) 16, \n\t"
1854 "rate = (int) [ 1, MAX ], \n\t"
1855 "channels = (int) ";
1856 gst_audio_caps += fmts16[i].chans;
1857 gst_audio_caps += ", \n\t"
1858 "channel-positions = (GstAudioChannelPosition) < ";
1859 gst_audio_caps += fmts16[i].order;
1860 gst_audio_caps += " >; \n";
1862 for(int i = 0;fmts8[i].ename;i++)
1864 if(alGetEnumValue(fmts8[i].ename) == 0)
1865 continue;
1867 gst_audio_caps +=
1868 "audio/x-raw-int, \n\t"
1869 "signed = (boolean) FALSE, \n\t"
1870 "width = (int) 8, \n\t"
1871 "depth = (int) 8, \n\t"
1872 "rate = (int) [ 1, MAX ], \n\t"
1873 "channels = (int) ";
1874 gst_audio_caps += fmts8[i].chans;
1875 gst_audio_caps += ", \n\t"
1876 "channel-positions = (GstAudioChannelPosition) < ";
1877 gst_audio_caps += fmts8[i].order;
1878 gst_audio_caps += " >; \n";
1881 else
1883 if(alIsExtensionPresent("AL_EXT_FLOAT32"))
1885 gst_audio_caps +=
1886 "audio/x-raw-float, \n\t"
1887 "endianness = (int) { " G_STRINGIFY(G_BYTE_ORDER) " }, \n\t"
1888 "signed = (boolean) TRUE, \n\t"
1889 "width = (int) 32, \n\t"
1890 "depth = (int) 32, \n\t"
1891 "rate = (int) [ 1, MAX ], \n\t"
1892 "channels = (int) [ 1, 2 ]; \n";
1894 gst_audio_caps +=
1895 "audio/x-raw-int, \n\t"
1896 "endianness = (int) { " G_STRINGIFY(G_BYTE_ORDER) " }, \n\t"
1897 "signed = (boolean) TRUE, \n\t"
1898 "width = (int) 16, \n\t"
1899 "depth = (int) 16, \n\t"
1900 "rate = (int) [ 1, MAX ], \n\t"
1901 "channels = (int) [ 1, 2 ]; \n";
1902 gst_audio_caps +=
1903 "audio/x-raw-int, \n\t"
1904 "signed = (boolean) FALSE, \n\t"
1905 "width = (int) 8, \n\t"
1906 "depth = (int) 8, \n\t"
1907 "rate = (int) [ 1, MAX ], \n\t"
1908 "channels = (int) [ 1, 2 ]; \n";
1911 gchar *string = g_strdup_printf("appsrc name=alureSrc ! decodebin ! audioconvert ! appsink caps=\"%s\" name=alureSink", gst_audio_caps.c_str());
1912 gstPipeline = gst_parse_launch(string, NULL);
1913 g_free(string);
1915 if(!gstPipeline)
1916 return;
1918 GstElement *gstSrc = gst_bin_get_by_name(GST_BIN(gstPipeline), "alureSrc");
1919 GstElement *gstSink = gst_bin_get_by_name(GST_BIN(gstPipeline), "alureSink");
1921 if(gstSrc && gstSink)
1923 g_object_set(G_OBJECT(gstSrc), "size", (gint64)len, NULL);
1924 g_object_set(G_OBJECT(gstSrc), "stream-type", 2, NULL);
1926 /* configure the appsrc, we will push a buffer to appsrc when it
1927 * needs more data */
1928 g_signal_connect(gstSrc, "need-data", G_CALLBACK(feed_data), this);
1929 g_signal_connect(gstSrc, "seek-data", G_CALLBACK(seek_data), this);
1931 g_object_set(G_OBJECT(gstSink), "preroll-queue-len", 1, NULL);
1932 g_object_set(G_OBJECT(gstSink), "max-buffers", 2, NULL);
1933 g_object_set(G_OBJECT(gstSink), "drop", FALSE, NULL);
1934 g_object_set(G_OBJECT(gstSink), "sync", FALSE, NULL);
1936 GstBus *bus = gst_element_get_bus(gstPipeline);
1937 if(bus)
1939 const GstMessageType types = GstMessageType(GST_MESSAGE_ERROR|GST_MESSAGE_ASYNC_DONE);
1940 GstMessage *msg;
1942 gst_element_set_state(gstPipeline, GST_STATE_PLAYING);
1943 while((msg=gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, types)) != NULL)
1945 if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ASYNC_DONE)
1947 on_new_preroll_from_source(gstSink);
1948 gst_message_unref(msg);
1949 break;
1952 if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR)
1954 gchar *debug;
1955 GError *error;
1957 gst_message_parse_error(msg, &error, &debug);
1958 g_printerr("GST Error: %s\n", error->message);
1960 g_free(debug);
1961 g_error_free(error);
1963 gst_message_unref(msg);
1964 break;
1966 gst_message_unref(msg);
1969 gst_object_unref(bus);
1970 bus = NULL;
1974 if(gstSrc) gst_object_unref(gstSrc);
1975 if(gstSink) gst_object_unref(gstSink);
1977 if(format == AL_NONE)
1979 gst_element_set_state(gstPipeline, GST_STATE_NULL);
1980 gst_object_unref(gstPipeline);
1981 gstPipeline = NULL;
1985 void on_new_preroll_from_source(GstElement *elt)
1987 // get the buffer from appsink
1988 GstBuffer *buffer = gst_app_sink_pull_preroll(GST_APP_SINK(elt));
1989 if(!buffer)
1990 return;
1992 if(format == AL_NONE)
1994 GstCaps *caps = GST_BUFFER_CAPS(buffer);
1995 //GST_LOG("caps are %" GST_PTR_FORMAT, caps);
1997 ALint i;
1998 gint rate = 0, channels = 0, bits = 0;
1999 for(i = gst_caps_get_size(caps)-1;i >= 0;i--)
2001 GstStructure *struc = gst_caps_get_structure(caps, i);
2002 if(gst_structure_has_field(struc, "channels"))
2003 gst_structure_get_int(struc, "channels", &channels);
2004 if(gst_structure_has_field(struc, "rate"))
2005 gst_structure_get_int(struc, "rate", &rate);
2006 if(gst_structure_has_field(struc, "width"))
2007 gst_structure_get_int(struc, "width", &bits);
2010 samplerate = rate;
2011 if(bits == 32)
2012 format = alureGetSampleFormat(channels, 0, bits);
2013 else
2014 format = alureGetSampleFormat(channels, bits, 0);
2015 blockAlign = channels * bits / 8;
2018 /* we don't need the appsink buffer anymore */
2019 gst_buffer_unref(buffer);
2022 void on_new_buffer_from_source(GstElement *elt)
2024 // get the buffer from appsink
2025 GstBuffer *buffer = gst_app_sink_pull_buffer(GST_APP_SINK(elt));
2026 if(!buffer)
2027 return;
2029 ALubyte *src_buffer = (ALubyte*)(GST_BUFFER_DATA(buffer));
2030 guint size = GST_BUFFER_SIZE(buffer);
2031 guint rem = std::min(size, outLen-outTotal);
2032 if(rem > 0)
2033 memcpy(outBytes+outTotal, src_buffer, rem);
2034 outTotal += rem;
2036 if(size > rem)
2038 size_t start = initialData.size();
2039 initialData.resize(start+size-rem);
2040 memcpy(&initialData[start], src_buffer+rem, initialData.size()-start);
2043 /* we don't need the appsink buffer anymore */
2044 gst_buffer_unref(buffer);
2047 static void feed_data(GstElement *appsrc, guint size, gstStream *app)
2049 GstFlowReturn ret;
2051 if(!app->fstream->good())
2053 // we are EOS, send end-of-stream
2054 g_signal_emit_by_name(appsrc, "end-of-stream", &ret);
2055 return;
2058 // read any amount of data, we are allowed to return less if we are EOS
2059 GstBuffer *buffer = gst_buffer_new();
2060 void *data = g_malloc(size);
2062 app->fstream->read(static_cast<char*>(data), size);
2064 GST_BUFFER_SIZE(buffer) = app->fstream->gcount();
2065 GST_BUFFER_MALLOCDATA(buffer) = static_cast<guint8*>(data);
2066 GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer);
2068 //GST_DEBUG("feed buffer %p, %u", buffer, GST_BUFFER_SIZE(buffer));
2069 g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
2070 gst_buffer_unref(buffer);
2073 static gboolean seek_data(GstElement */*appsrc*/, guint64 position, gstStream *app)
2075 //GST_DEBUG("seek to offset %" G_GUINT64_FORMAT, position);
2076 app->fstream->clear();
2077 return (app->fstream->seekg(position) ? TRUE : FALSE);
2080 #else
2081 struct gstStream : public nullStream {
2082 gstStream(std::istream*){}
2084 #endif
2087 template <typename T>
2088 alureStream *get_stream_decoder(const T &fdata)
2090 alureStream *stream;
2092 std::map<ALint,UserCallbacks>::iterator i = InstalledCallbacks.begin();
2093 while(i != InstalledCallbacks.end() && i->first < 0)
2095 stream = new customStream(fdata, i->second);
2096 if(stream->IsValid())
2097 return stream;
2098 delete stream;
2099 i++;
2102 std::istream *file = new InStream(fdata);
2103 if(!file->fail())
2105 stream = new wavStream(file);
2106 if(stream->IsValid())
2107 return stream;
2108 delete stream;
2110 file->clear();
2111 file->seekg(0, std::ios_base::beg);
2112 stream = new aiffStream(file);
2113 if(stream->IsValid())
2114 return stream;
2115 delete stream;
2117 // Try libVorbisFile
2118 file->clear();
2119 file->seekg(0, std::ios_base::beg);
2120 stream = new oggStream(file);
2121 if(stream->IsValid())
2122 return stream;
2123 delete stream;
2125 // Try libFLAC
2126 file->clear();
2127 file->seekg(0, std::ios_base::beg);
2128 stream = new flacStream(file);
2129 if(stream->IsValid())
2130 return stream;
2131 delete stream;
2133 // Try DUMB
2134 file->clear();
2135 file->seekg(0, std::ios_base::beg);
2136 stream = new dumbStream(file);
2137 if(stream->IsValid())
2138 return stream;
2139 delete stream;
2141 // Try libSndFile
2142 file->clear();
2143 file->seekg(0, std::ios_base::beg);
2144 stream = new sndStream(file);
2145 if(stream->IsValid())
2146 return stream;
2147 delete stream;
2149 // Try MPG123
2150 file->clear();
2151 file->seekg(0, std::ios_base::beg);
2152 stream = new mp3Stream(file);
2153 if(stream->IsValid())
2154 return stream;
2155 delete stream;
2157 // Try Timidity
2158 file->clear();
2159 file->seekg(0, std::ios_base::beg);
2160 stream = new midiStream(file);
2161 if(stream->IsValid())
2162 return stream;
2163 delete stream;
2165 // Try GStreamer
2166 file->clear();
2167 file->seekg(0, std::ios_base::beg);
2168 stream = new gstStream(file);
2169 if(stream->IsValid())
2170 return stream;
2171 delete stream;
2173 SetError("Unsupported type");
2174 delete file;
2176 else
2178 SetError("Failed to open file");
2179 delete file;
2182 while(i != InstalledCallbacks.end())
2184 stream = new customStream(fdata, i->second);
2185 if(stream->IsValid())
2186 return stream;
2187 delete stream;
2188 i++;
2191 return new nullStream;
2194 alureStream *create_stream(const char *fname)
2195 { return get_stream_decoder(fname); }
2196 alureStream *create_stream(const MemDataInfo &memData)
2197 { return get_stream_decoder(memData); }